Commit 1ae4482f authored by Vivien Kraus's avatar Vivien Kraus
Browse files

Run frama-c-gui

The =frama-c-gui= target now runs the Frama-c GUI.  You can do:

  make frama-c-gui
parent c0100ed0
...@@ -21,6 +21,7 @@ stages: ...@@ -21,6 +21,7 @@ stages:
- manual - manual
dist: dist:
image: tarotbis/dist
stage: dist stage: dist
script: "./ci/dist.sh" script: "./ci/dist.sh"
artifacts: artifacts:
...@@ -29,11 +30,12 @@ dist: ...@@ -29,11 +30,12 @@ dist:
expire_in: 1 week expire_in: 1 week
check: check:
image: tarotbis/check
stage: check stage: check
script: "./ci/check.sh" script: "./ci/check.sh"
mingw: mingw:
image: fedora image: tarotbis/mingw
stage: check stage: check
script: "./ci/mingw.sh" script: "./ci/mingw.sh"
artifacts: artifacts:
...@@ -42,6 +44,7 @@ mingw: ...@@ -42,6 +44,7 @@ mingw:
expire_in: 1 week expire_in: 1 week
deb: deb:
image: tarotbis/deb
stage: check stage: check
script: "./ci/deb.sh" script: "./ci/deb.sh"
artifacts: artifacts:
...@@ -50,6 +53,7 @@ deb: ...@@ -50,6 +53,7 @@ deb:
expire_in: 1 week expire_in: 1 week
pages: pages:
image: tarotbis/pages
stage: manual stage: manual
script: "./ci/pages.sh" script: "./ci/pages.sh"
artifacts: artifacts:
......
...@@ -46,6 +46,7 @@ include flatpak/Makefile.am ...@@ -46,6 +46,7 @@ include flatpak/Makefile.am
include git-check.am include git-check.am
include copyright/Makefile.am include copyright/Makefile.am
include guix/Makefile.am include guix/Makefile.am
include framac.am
AM_CPPFLAGS += \ AM_CPPFLAGS += \
-DLOCALEDIR="\"$(localedir)\"" \ -DLOCALEDIR="\"$(localedir)\"" \
......
...@@ -19,6 +19,7 @@ apt-get upgrade -y ...@@ -19,6 +19,7 @@ apt-get upgrade -y
apt-get install -y \ apt-get install -y \
build-essential \ build-essential \
guile-2.2-dev \ guile-2.2-dev \
frama-c \
libglib2.0-dev \ libglib2.0-dev \
nettle-dev \ nettle-dev \
pkg-config \ pkg-config \
......
...@@ -32,6 +32,7 @@ apt-get install -y \ ...@@ -32,6 +32,7 @@ apt-get install -y \
devscripts \ devscripts \
emacs \ emacs \
emacs-goodies-el \ emacs-goodies-el \
frama-c-base \
gcc \ gcc \
gettext \ gettext \
git \ git \
...@@ -72,6 +73,7 @@ sh autogen.sh VALAFLAGS="--target-glib=2.50" || exit 1 ...@@ -72,6 +73,7 @@ sh autogen.sh VALAFLAGS="--target-glib=2.50" || exit 1
--prefix="$SOURCE_TOP/dist" \ --prefix="$SOURCE_TOP/dist" \
--enable-valgrind=yes \ --enable-valgrind=yes \
--enable-silent-rules=yes \ --enable-silent-rules=yes \
--enable-static-analysis=yes \
|| (cat config.log ; exit 1) \ || (cat config.log ; exit 1) \
|| exit 1 || exit 1
make .version || exit 1 make .version || exit 1
......
...@@ -109,6 +109,17 @@ AS_IF([test "x$GUIX" != "xno"], [ ...@@ -109,6 +109,17 @@ AS_IF([test "x$GUIX" != "xno"], [
AC_SUBST([GUIX]) AC_SUBST([GUIX])
]) ])
AM_CONDITIONAL([HAVE_GUIX], [test "x$GUIX" != "xno"]) AM_CONDITIONAL([HAVE_GUIX], [test "x$GUIX" != "xno"])
AC_ARG_ENABLE([static-analysis], AS_HELP_STRING([--enable-static-analysis=yes], [Run a static analyser as part of 'make check']))
ENABLE_FRAMA_C="no"
AS_IF([test "x$enable_static_analysis" = "xyes"], [
AC_CHECK_PROGS([FRAMA_C], [frama-c], [no])
AS_IF([test "x$FRAMA_C" = "xno"], [
AC_MSG_ERROR([No static analyzer.])
])
ENABLE_FRAMA_C="yes"
])
AM_MISSING_PROG([FRAMA_C_GUI], [frama-c-gui])
AM_CONDITIONAL([HAVE_FRAMA_C], [test "x$ENABLE_FRAMA_C" != "xno"])
# Checks for libraries. # Checks for libraries.
gl_INIT gl_INIT
...@@ -123,7 +134,7 @@ AS_IF([test "x$enable_program" != "xno"], [ ...@@ -123,7 +134,7 @@ AS_IF([test "x$enable_program" != "xno"], [
AC_MSG_ERROR([Gtk+ was not found.]) AC_MSG_ERROR([Gtk+ was not found.])
]) ])
]) ])
AX_LIB_NETTLE([yes]) PKG_CHECK_MODULES([NETTLE], [nettle])
AC_ARG_WITH([gobject], AS_HELP_STRING([--without-gobject], [Do not build the GObject bindings])) AC_ARG_WITH([gobject], AS_HELP_STRING([--without-gobject], [Do not build the GObject bindings]))
WITH_GOBJECT="no" WITH_GOBJECT="no"
AS_IF([test "x$with_gobject" != "xno"], [ AS_IF([test "x$with_gobject" != "xno"], [
......
...@@ -46,7 +46,8 @@ case "$1" in ...@@ -46,7 +46,8 @@ case "$1" in
| ./po/LINGUAS | ./po/*.po | ./po/*.pot | ./src/libtarot/xml/check_xml_*.xml \ | ./po/LINGUAS | ./po/*.po | ./po/*.pot | ./src/libtarot/xml/check_xml_*.xml \
| ./debian/source/format | ./debian/compat | ./.gitmodules \ | ./debian/source/format | ./debian/compat | ./.gitmodules \
| ./src/libtarot/perceptron/tarot/perceptron_private_static_structure.h \ | ./src/libtarot/perceptron/tarot/perceptron_private_static_structure.h \
| ./src/libtarot/perceptron/tarot/perceptron_private_static_weights.h) | ./src/libtarot/perceptron/tarot/perceptron_private_static_weights.h \
| ./spy_makefile.mk)
exit 0 exit 0
;; ;;
*.am | *.desktop.in | *.org | ./debian/source/format | ./debian/compat | ./configure.ac \ *.am | *.desktop.in | *.org | ./debian/source/format | ./debian/compat | ./configure.ac \
......
# tarot implements the rules of the tarot game # tarot implements the rules of the tarot game
# Copyright (C) 2017, 2018, 2019 Vivien Kraus # Copyright (C) 2017, 2018, 2019, 2020 Vivien Kraus
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
...@@ -87,3 +87,4 @@ dist_vapi_DATA = ...@@ -87,3 +87,4 @@ dist_vapi_DATA =
INTROSPECTION_GIRS = INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = INTROSPECTION_SCANNER_ARGS =
VAPIGEN_VAPIS = VAPIGEN_VAPIS =
ACSL_ANNOTATED =
# tarot implements the rules of the tarot game
# Copyright (C) 2020 Vivien Kraus
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
.PHONY: frama-c-gui frama-c-wp
frama_c_gui_verbose = $(frama_c_gui_verbose_@AM_V@)
frama_c_gui_verbose_ = $(frama_c_gui_verbose_@AM_DEFAULT_V@)
frama_c_gui_verbose_0 = @echo " FRAMACGUI";
frama_c_verbose = $(frama_c_verbose_@AM_V@)
frama_c_verbose_ = $(frama_c_verbose_@AM_DEFAULT_V@)
frama_c_verbose_0 = @echo " FRAMAC ";
EXTRA_DIST += spy_makefile.mk
if HAVE_FRAMA_C
check-local: frama-c-wp
endif # HAVE_FRAMA_C
FRAMAC_DECLARATIONS = "struct locale_t_unknown; typedef struct locale_t_unknown * locale_t; locale_t uselocale (void *p); char __fc_strerror[64];"
FRAMAC_CFLAGS_ADDED = -I$$($(FRAMA_C) -print-share-path)/libc -nostdinc -D__FC_MACHDEP_X86_64 -include $(abs_top_builddir)/fake_locale.h -DLC_GLOBAL_LOCALE=NULL -I /usr/include
FRAMAC_LIBS_ADDED = $(abs_top_builddir)/__fc_runtime.o
FRAMAC_COMPILE_DEFINITIONS = (rm -f $(abs_top_builddir)/__fc_runtime.o && $(CC) $(FRAMAC_CFLAGS_ADDED) -o $(abs_top_builddir)/__fc_runtime.o -c $$($(FRAMA_C) -print-share-path)/libc/__fc_runtime.c)
CLEANFILES += framac-lib
FRAMAC_PREPARE = echo $(FRAMAC_DECLARATIONS) > fake_locale.h && $(FRAMAC_COMPILE_DEFINITIONS)
frama-c-gui: $(ACSL_ANNOTATED)
$(frama_c_gui_verbose) $(FRAMA_C_GUI) -cpp-extra-args='$(AM_CPPFLAGS) $(AM_CFLAGS) $(CPPFLAGS) $(CFLAGS) -D_Noreturn= -I/usr/include -DPACKAGE=\"$(PACKAGE)\"' -wp-rte $(ACSL_ANNOTATED)
frama-c-wp: $(ACSL_ANNOTATED)
$(frama_c_verbose) $(FRAMA_C) -cpp-extra-args='$(AM_CPPFLAGS) $(AM_CFLAGS) $(CPPFLAGS) $(CFLAGS) -D_Noreturn= -I/usr/include -DPACKAGE=\"$(PACKAGE)\"' -wp -wp-rte $(ACSL_ANNOTATED) 2>&1 | tee output | grep -v '\[wp\].*: Valid$$'
@ export RATIO=$$(grep '\[wp\] Proved goals:' output | cut -d ':' -f 2); export PROVED=$$(echo $$(echo "$$RATIO" | cut -d '/' -f 1)) TOTAL=$$(echo $$(echo "$$RATIO" | cut -d '/' -f 2)); >&2 echo "Proved goals: $$PROVED / $$TOTAL" && test "x$$PROVED" = "x$$TOTAL" && test "x$$PROVED" != "x" && rm -f output
# tarot implements the rules of the tarot game # tarot implements the rules of the tarot game
# Copyright (C) 2018, 2019 Vivien Kraus # Copyright (C) 2018, 2019, 2020 Vivien Kraus
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
...@@ -15,3 +15,5 @@ ...@@ -15,3 +15,5 @@
lib/libgnu.la: lib/libgnu.la:
$(MAKE) $(AM_MAKEFLAGS) -C lib $(MAKE) $(AM_MAKEFLAGS) -C lib
AM_CPPFLAGS += -I lib -I $(srcdir)/lib
...@@ -8,7 +8,7 @@ msgid "" ...@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: tarot 0.4.2.83-ebdc-dirty\n" "Project-Id-Version: tarot 0.4.2.83-ebdc-dirty\n"
"Report-Msgid-Bugs-To: vivien@planete-kraus.eu\n" "Report-Msgid-Bugs-To: vivien@planete-kraus.eu\n"
"POT-Creation-Date: 2020-01-11 15:25+0100\n" "POT-Creation-Date: 2020-01-25 11:50+0100\n"
"PO-Revision-Date: 2020-01-02 19:27+0100\n" "PO-Revision-Date: 2020-01-02 19:27+0100\n"
"Last-Translator: Vivien Kraus <vivien@planete-kraus.eu>\n" "Last-Translator: Vivien Kraus <vivien@planete-kraus.eu>\n"
"Language-Team: French\n" "Language-Team: French\n"
...@@ -90,139 +90,139 @@ msgstr "Jouer au tarot contre l'IA" ...@@ -90,139 +90,139 @@ msgstr "Jouer au tarot contre l'IA"
msgid "Vivien Kraus" msgid "Vivien Kraus"
msgstr "Vivien Kraus" msgstr "Vivien Kraus"
#: src/libtarot/cards/tarot/cards_private_impl.h:93 #: src/libtarot/cards/tarot/cards_private_impl.h:121
msgid "AH" msgid "AH"
msgstr "AC" msgstr "AC"
#: src/libtarot/cards/tarot/cards_private_impl.h:94 #: src/libtarot/cards/tarot/cards_private_impl.h:121
msgid "2H" msgid "2H"
msgstr "2C" msgstr "2C"
#: src/libtarot/cards/tarot/cards_private_impl.h:95 #: src/libtarot/cards/tarot/cards_private_impl.h:121
msgid "3H" msgid "3H"
msgstr "3C" msgstr "3C"
#: src/libtarot/cards/tarot/cards_private_impl.h:96 #: src/libtarot/cards/tarot/cards_private_impl.h:121
msgid "4H" msgid "4H"
msgstr "4C" msgstr "4C"
#: src/libtarot/cards/tarot/cards_private_impl.h:97 #: src/libtarot/cards/tarot/cards_private_impl.h:121
msgid "5H" msgid "5H"
msgstr "5C" msgstr "5C"
#: src/libtarot/cards/tarot/cards_private_impl.h:98 #: src/libtarot/cards/tarot/cards_private_impl.h:122
msgid "6H" msgid "6H"
msgstr "6C" msgstr "6C"
#: src/libtarot/cards/tarot/cards_private_impl.h:99 #: src/libtarot/cards/tarot/cards_private_impl.h:122
msgid "7H" msgid "7H"
msgstr "7C" msgstr "7C"
#: src/libtarot/cards/tarot/cards_private_impl.h:100 #: src/libtarot/cards/tarot/cards_private_impl.h:122
msgid "8H" msgid "8H"
msgstr "8C" msgstr "8C"
#: src/libtarot/cards/tarot/cards_private_impl.h:101 #: src/libtarot/cards/tarot/cards_private_impl.h:122
msgid "9H" msgid "9H"
msgstr "9C" msgstr "9C"
#: src/libtarot/cards/tarot/cards_private_impl.h:102 #: src/libtarot/cards/tarot/cards_private_impl.h:122
msgid "10H" msgid "10H"
msgstr "10C" msgstr "10C"
#: src/libtarot/cards/tarot/cards_private_impl.h:103 #: src/libtarot/cards/tarot/cards_private_impl.h:123
msgid "JH" msgid "JH"
msgstr "VC" msgstr "VC"
#: src/libtarot/cards/tarot/cards_private_impl.h:104 #: src/libtarot/cards/tarot/cards_private_impl.h:123
msgid "CH" msgid "CH"
msgstr "CC" msgstr "CC"
#: src/libtarot/cards/tarot/cards_private_impl.h:105 #: src/libtarot/cards/tarot/cards_private_impl.h:123
msgid "QH" msgid "QH"
msgstr "DC" msgstr "DC"
#: src/libtarot/cards/tarot/cards_private_impl.h:106 #: src/libtarot/cards/tarot/cards_private_impl.h:123
msgid "KH" msgid "KH"
msgstr "RC" msgstr "RC"
#: src/libtarot/cards/tarot/cards_private_impl.h:107 #: src/libtarot/cards/tarot/cards_private_impl.h:123
msgid "AC" msgid "AC"
msgstr "AT" msgstr "AT"
#: src/libtarot/cards/tarot/cards_private_impl.h:108 #: src/libtarot/cards/tarot/cards_private_impl.h:124
msgid "2C" msgid "2C"
msgstr "2T" msgstr "2T"
#: src/libtarot/cards/tarot/cards_private_impl.h:109 #: src/libtarot/cards/tarot/cards_private_impl.h:124
msgid "3C" msgid "3C"
msgstr "3T" msgstr "3T"
#: src/libtarot/cards/tarot/cards_private_impl.h:110 #: src/libtarot/cards/tarot/cards_private_impl.h:124
msgid "4C" msgid "4C"
msgstr "4T" msgstr "4T"
#: src/libtarot/cards/tarot/cards_private_impl.h:111 #: src/libtarot/cards/tarot/cards_private_impl.h:124
msgid "5C" msgid "5C"
msgstr "5T" msgstr "5T"
#: src/libtarot/cards/tarot/cards_private_impl.h:112 #: src/libtarot/cards/tarot/cards_private_impl.h:124
msgid "6C" msgid "6C"
msgstr "6T" msgstr "6T"
#: src/libtarot/cards/tarot/cards_private_impl.h:113 #: src/libtarot/cards/tarot/cards_private_impl.h:125
msgid "7C" msgid "7C"
msgstr "7T" msgstr "7T"
#: src/libtarot/cards/tarot/cards_private_impl.h:114 #: src/libtarot/cards/tarot/cards_private_impl.h:125
msgid "8C" msgid "8C"
msgstr "8T" msgstr "8T"
#: src/libtarot/cards/tarot/cards_private_impl.h:115 #: src/libtarot/cards/tarot/cards_private_impl.h:125
msgid "9C" msgid "9C"
msgstr "9T" msgstr "9T"
#: src/libtarot/cards/tarot/cards_private_impl.h:116 #: src/libtarot/cards/tarot/cards_private_impl.h:125
msgid "10C" msgid "10C"
msgstr "10T" msgstr "10T"
#: src/libtarot/cards/tarot/cards_private_impl.h:117 #: src/libtarot/cards/tarot/cards_private_impl.h:125
msgid "JC" msgid "JC"
msgstr "VT" msgstr "VT"
#: src/libtarot/cards/tarot/cards_private_impl.h:118 #: src/libtarot/cards/tarot/cards_private_impl.h:126
msgid "CC" msgid "CC"
msgstr "CT" msgstr "CT"
#: src/libtarot/cards/tarot/cards_private_impl.h:119 #: src/libtarot/cards/tarot/cards_private_impl.h:126
msgid "QC" msgid "QC"
msgstr "DT" msgstr "DT"
#: src/libtarot/cards/tarot/cards_private_impl.h:120 #: src/libtarot/cards/tarot/cards_private_impl.h:126
msgid "KC" msgid "KC"
msgstr "RT" msgstr "RT"
#: src/libtarot/cards/tarot/cards_private_impl.h:121 #: src/libtarot/cards/tarot/cards_private_impl.h:126
msgid "AD" msgid "AD"
msgstr "AK" msgstr "AK"
#: src/libtarot/cards/tarot/cards_private_impl.h:122 #: src/libtarot/cards/tarot/cards_private_impl.h:126
msgid "2D" msgid "2D"
msgstr "2K" msgstr "2K"
#: src/libtarot/cards/tarot/cards_private_impl.h:123 #: src/libtarot/cards/tarot/cards_private_impl.h:127
msgid "3D" msgid "3D"
msgstr "3K" msgstr "3K"
#: src/libtarot/cards/tarot/cards_private_impl.h:124 #: src/libtarot/cards/tarot/cards_private_impl.h:127
msgid "4D" msgid "4D"
msgstr "4K" msgstr "4K"
#: src/libtarot/cards/tarot/cards_private_impl.h:125 #: src/libtarot/cards/tarot/cards_private_impl.h:127
msgid "5D" msgid "5D"
msgstr "5K" msgstr "5K"
#: src/libtarot/cards/tarot/cards_private_impl.h:126 #: src/libtarot/cards/tarot/cards_private_impl.h:127
msgid "6D" msgid "6D"
msgstr "6K" msgstr "6K"
...@@ -234,171 +234,171 @@ msgstr "7K" ...@@ -234,171 +234,171 @@ msgstr "7K"
msgid "8D" msgid "8D"
msgstr "8K" msgstr "8K"
#: src/libtarot/cards/tarot/cards_private_impl.h:129 #: src/libtarot/cards/tarot/cards_private_impl.h:128
msgid "9D" msgid "9D"
msgstr "9K" msgstr "9K"
#: src/libtarot/cards/tarot/cards_private_impl.h:130 #: src/libtarot/cards/tarot/cards_private_impl.h:128
msgid "10D" msgid "10D"
msgstr "10K" msgstr "10K"
#: src/libtarot/cards/tarot/cards_private_impl.h:131 #: src/libtarot/cards/tarot/cards_private_impl.h:128
msgid "JD" msgid "JD"
msgstr "VK" msgstr "VK"
#: src/libtarot/cards/tarot/cards_private_impl.h:132 #: src/libtarot/cards/tarot/cards_private_impl.h:128
msgid "CD" msgid "CD"
msgstr "CK" msgstr "CK"
#: src/libtarot/cards/tarot/cards_private_impl.h:133 #: src/libtarot/cards/tarot/cards_private_impl.h:129
msgid "QD" msgid "QD"
msgstr "DK" msgstr "DK"
#: src/libtarot/cards/tarot/cards_private_impl.h:134 #: src/libtarot/cards/tarot/cards_private_impl.h:129
msgid "KD" msgid "KD"
msgstr "RK" msgstr "RK"
#: src/libtarot/cards/tarot/cards_private_impl.h:135 #: src/libtarot/cards/tarot/cards_private_impl.h:129
msgid "AS" msgid "AS"
msgstr "AP" msgstr "AP"
#: src/libtarot/cards/tarot/cards_private_impl.h:136 #: src/libtarot/cards/tarot/cards_private_impl.h:129
msgid "2S" msgid "2S"
msgstr "2P" msgstr "2P"
#: src/libtarot/cards/tarot/cards_private_impl.h:137 #: src/libtarot/cards/tarot/cards_private_impl.h:129
msgid "3S" msgid "3S"
msgstr "3P" msgstr "3P"
#: src/libtarot/cards/tarot/cards_private_impl.h:138 #: src/libtarot/cards/tarot/cards_private_impl.h:130
msgid "4S" msgid "4S"
msgstr "4P" msgstr "4P"
#: src/libtarot/cards/tarot/cards_private_impl.h:139 #: src/libtarot/cards/tarot/cards_private_impl.h:130
msgid "5S" msgid "5S"
msgstr "5P" msgstr "5P"
#: src/libtarot/cards/tarot/cards_private_impl.h:140 #: src/libtarot/cards/tarot/cards_private_impl.h:130
msgid "6S" msgid "6S"
msgstr "6P" msgstr "6P"
#: src/libtarot/cards/tarot/cards_private_impl.h:141 #: src/libtarot/cards/tarot/cards_private_impl.h:130
msgid "7S" msgid "7S"
msgstr "7P" msgstr "7P"
#: src/libtarot/cards/tarot/cards_private_impl.h:142 #: src/libtarot/cards/tarot/cards_private_impl.h:130
msgid "8S" msgid "8S"
msgstr "8P" msgstr "8P"
#: src/libtarot/cards/tarot/cards_private_impl.h:143 #: src/libtarot/cards/tarot/cards_private_impl.h:131
msgid "9S" msgid "9S"
msgstr "9P" msgstr "9P"
#: src/libtarot/cards/tarot/cards_private_impl.h:144 #: src/libtarot/cards/tarot/cards_private_impl.h:131
msgid "10S" msgid "10S"
msgstr "10P" msgstr "10P"
#: src/libtarot/cards/tarot/cards_private_impl.h:145 #: src/libtarot/cards/tarot/cards_private_impl.h:131
msgid "JS" msgid "JS"
msgstr "VP" msgstr "VP"
#: src/libtarot/cards/tarot/cards_private_impl.h:146 #: src/libtarot/cards/tarot/cards_private_impl.h:131
msgid "CS" msgid "CS"
msgstr "CP" msgstr "CP"
#: src/libtarot/cards/tarot/cards_private_impl.h:147 #: src/libtarot/cards/tarot/cards_private_impl.h:131
msgid "QS" msgid "QS"
msgstr "DP" msgstr "DP"
#: src/libtarot/cards/tarot/cards_private_impl.h:148 #: src/libtarot/cards/tarot/cards_private_impl.h:132
msgid "KS"