scripts/build/libc/eglibc.sh
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Wed Jan 13 20:46:01 2010 +0100 (2010-01-13)
changeset 1732 6b2ae7804c6f
parent 1552 6ee673ab382e
child 1761 88020b2c3246
permissions -rw-r--r--
debug/gdb: staticaly link to ncurses for the native gdb

Staticaly link the native gdb (the one that runs on the target,
not the cross one that runs on the host) to ncurses.
yann@850
     1
# eglibc build functions (initially by Thomas JOURDAN).
yann@850
     2
yann@850
     3
# Download eglibc repository
yann@850
     4
do_eglibc_get() {
yann@850
     5
    CT_HasOrAbort svn
yann@850
     6
yann@850
     7
    case "${CT_LIBC_VERSION}" in
yann@850
     8
        trunk)  svn_url="svn://svn.eglibc.org/trunk";;
yann@850
     9
        *)      svn_url="svn://svn.eglibc.org/branches/eglibc-${CT_LIBC_VERSION}";;
yann@850
    10
    esac
yann@850
    11
yann@850
    12
    case "${CT_EGLIBC_CHECKOUT}" in
yann@850
    13
        y)  svn_action="checkout";;
yann@850
    14
        *)  svn_action="export --force";;
yann@850
    15
    esac
yann@850
    16
yann@850
    17
    CT_DoExecLog ALL svn ${svn_action} -r "${CT_EGLIBC_REVISION:-HEAD}" "${svn_url}" . 2>&1
yann@850
    18
yann@850
    19
    # Compress eglibc
yann@1123
    20
    CT_DoExecLog ALL mv libc "eglibc-${CT_LIBC_VERSION}"
yann@1123
    21
    CT_DoExecLog ALL tar cjf "eglibc-${CT_LIBC_VERSION}.tar.bz2" "eglibc-${CT_LIBC_VERSION}"
yann@850
    22
yann@850
    23
    # Compress linuxthreads, localedef and ports
yann@850
    24
    # Assign them the name the way ct-ng like it
yann@850
    25
    for addon in linuxthreads localedef ports; do
yann@1123
    26
        CT_DoExecLog ALL mv "${addon}" "eglibc-${addon}-${CT_LIBC_VERSION}"
yann@1123
    27
        CT_DoExecLog ALL tar cjf "eglibc-${addon}-${CT_LIBC_VERSION}.tar.bz2" "eglibc-${addon}-${CT_LIBC_VERSION}"
yann@850
    28
    done
yann@850
    29
}
yann@850
    30
yann@850
    31
# Download glibc
yann@850
    32
do_libc_get() {
yann@850
    33
    # eglibc is only available through subversion, there are no
yann@850
    34
    # snapshots available. Moreover, addons will be downloaded
yann@850
    35
    # simultaneously.
yann@850
    36
yann@850
    37
    # build filename
yann@1123
    38
    eglibc="eglibc-${CT_LIBC_VERSION}.tar.bz2"
yann@850
    39
    eglibc_linuxthreads="${CT_LIBC}-linuxthreads-${CT_LIBC_VERSION}.tar.bz2"
yann@850
    40
    eglibc_localedef="${CT_LIBC}-localedef-${CT_LIBC_VERSION}.tar.bz2"
yann@850
    41
    eglibc_ports="${CT_LIBC}-ports-${CT_LIBC_VERSION}.tar.bz2"
yann@850
    42
yann@850
    43
    # Check if every tarballs are already present
yann@1476
    44
    if [    -f "${CT_TARBALLS_DIR}/${eglibc}"                   \
yann@1476
    45
         -a -f "${CT_TARBALLS_DIR}/${eglibc_linuxthreads}"      \
yann@1476
    46
         -a -f "${CT_TARBALLS_DIR}/${eglibc_localedef}"         \
yann@1476
    47
         -a -f "${CT_TARBALLS_DIR}/${eglibc_ports}"             \
yann@1476
    48
       ]; then
yann@850
    49
        CT_DoLog DEBUG "Already have 'eglibc-${CT_LIBC_VERSION}'"
yann@850
    50
        return 0
yann@850
    51
    fi
yann@850
    52
yann@1476
    53
    if [    -f "${CT_LOCAL_TARBALLS_DIR}/${eglibc}"                 \
yann@1476
    54
         -a -f "${CT_LOCAL_TARBALLS_DIR}/${eglibc_linuxthreads}"    \
yann@1476
    55
         -a -f "${CT_LOCAL_TARBALLS_DIR}/${eglibc_localedef}"       \
yann@1476
    56
         -a -f "${CT_LOCAL_TARBALLS_DIR}/${eglibc_ports}"           \
yann@1528
    57
         -a "${CT_FORCE_DOWNLOAD}" != "y"                           \
yann@1476
    58
       ]; then
yann@850
    59
        CT_DoLog DEBUG "Got 'eglibc-${CT_LIBC_VERSION}' from local storage"
yann@850
    60
        for file in ${eglibc} ${eglibc_linuxthreads} ${eglibc_localedef} ${eglibc_ports}; do
yann@850
    61
            CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${file}" "${CT_TARBALLS_DIR}/${file}"
yann@850
    62
        done
yann@850
    63
        return 0
yann@850
    64
    fi
yann@850
    65
yann@850
    66
    # Not found locally, try from the network
yann@850
    67
    CT_DoLog EXTRA "Retrieving 'eglibc-${CT_LIBC_VERSION}'"
yann@867
    68
yann@867
    69
    CT_MktempDir tmp_dir
yann@867
    70
    CT_Pushd "${tmp_dir}"
yann@867
    71
yann@850
    72
    do_eglibc_get
yann@867
    73
    CT_DoLog DEBUG "Moving 'eglibc-${CT_LIBC_VERSION}' to tarball directory"
yann@867
    74
    for file in ${eglibc} ${eglibc_linuxthreads} ${eglibc_localedef} ${eglibc_ports}; do
yann@867
    75
        CT_DoExecLog ALL mv -f "${file}" "${CT_TARBALLS_DIR}"
yann@867
    76
    done
yann@867
    77
yann@867
    78
    CT_Popd
yann@867
    79
yann@867
    80
    # Remove source files
yann@867
    81
    CT_DoExecLog ALL rm -rf "${tmp_dir}"
yann@850
    82
yann@850
    83
    if [ "${CT_SAVE_TARBALLS}" = "y" ]; then
yann@850
    84
        CT_DoLog EXTRA "Saving 'eglibc-${CT_LIBC_VERSION}' to local storage"
yann@850
    85
        for file in ${eglibc} ${eglibc_linuxthreads} ${eglibc_localedef} ${eglibc_ports}; do
yann@850
    86
            CT_DoExecLog ALL mv -f "${CT_TARBALLS_DIR}/${file}" "${CT_LOCAL_TARBALLS_DIR}"
yann@850
    87
            CT_DoExecLog ALL ln -s "${CT_LOCAL_TARBALLS_DIR}/${file}" "${CT_TARBALLS_DIR}/${file}"
yann@850
    88
        done
yann@850
    89
    fi
yann@850
    90
yann@850
    91
    return 0
yann@850
    92
}
yann@850
    93
yann@850
    94
# Extract eglibc
yann@850
    95
do_libc_extract() {
yann@1126
    96
    CT_Extract "eglibc-${CT_LIBC_VERSION}"
yann@1126
    97
    CT_Patch "eglibc-${CT_LIBC_VERSION}"
yann@850
    98
yann@850
    99
    # C library addons
yann@850
   100
    for addon in $(do_libc_add_ons_list " "); do
yann@850
   101
        # NPTL addon is not to be extracted, in any case
yann@850
   102
        [ "${addon}" = "nptl" ] && continue || true
yann@1123
   103
        CT_Pushd "${CT_SRC_DIR}/eglibc-${CT_LIBC_VERSION}"
yann@1126
   104
        CT_Extract "eglibc-${addon}-${CT_LIBC_VERSION}" nochdir
yann@1126
   105
        # Some addons have the 'long' name, while others have the
yann@1126
   106
        # 'short' name, but patches are non-uniformly built with
yann@1126
   107
        # either the 'long' or 'short' name, whatever the addons name
yann@1126
   108
        # so we have to make symlinks from the existing to the missing
yann@1126
   109
        # Fortunately for us, [ -d foo ], when foo is a symlink to a
yann@1126
   110
        # directory, returns true!
yann@1126
   111
        [ -d "${addon}" ] || ln -s "eglibc-${addon}-${CT_LIBC_VERSION}" "${addon}"
yann@1126
   112
        [ -d "eglibc-${addon}-${CT_LIBC_VERSION}" ] || ln -s "${addon}" "eglibc-${addon}-${CT_LIBC_VERSION}"
yann@1126
   113
        CT_Patch "eglibc-${addon}-${CT_LIBC_VERSION}" nochdir
yann@1123
   114
        CT_Popd
yann@850
   115
    done
yann@850
   116
yann@884
   117
    # The configure files may be older than the configure.in files
yann@884
   118
    # if using a snapshot (or even some tarballs). Fake them being
yann@884
   119
    # up to date.
yann@1123
   120
    find "${CT_SRC_DIR}/eglibc-${CT_LIBC_VERSION}" -type f -name configure -exec touch {} \; 2>&1 |CT_DoLog ALL
yann@884
   121
yann@850
   122
    return 0
yann@850
   123
}
yann@850
   124
avrac@1569
   125
# Copy user provided eglibc configuration file if provided
yann@850
   126
do_libc_check_config() {
avrac@1569
   127
    if [ "${CT_EGLIBC_CUSTOM_CONFIG}" != "y" ]; then
avrac@1569
   128
        return 0
avrac@1569
   129
    fi
avrac@1569
   130
avrac@1569
   131
    CT_DoStep INFO "Checking C library configuration"
avrac@1569
   132
avrac@1569
   133
    CT_TestOrAbort "You did not provide an eglibc config file!" \
avrac@1569
   134
        -n "${CT_EGLIBC_OPTION_GROUPS_FILE}" -a \
avrac@1569
   135
        -f "${CT_EGLIBC_OPTION_GROUPS_FILE}"
avrac@1569
   136
avrac@1569
   137
    CT_DoExecLog ALL cp "${CT_EGLIBC_OPTION_GROUPS_FILE}" "${CT_CONFIG_DIR}/eglibc.config"
avrac@1569
   138
avrac@1569
   139
    # NSS configuration
avrac@1569
   140
    if grep -E '^OPTION_EGLIBC_NSSWITCH[[:space:]]*=[[:space:]]*n' "${CT_EGLIBC_OPTION_GROUPS_FILE}" >/dev/null 2>&1; then
avrac@1569
   141
        CT_DoLog DEBUG "Using fixed-configuration nsswitch facility"
avrac@1569
   142
avrac@1569
   143
        if [ "${CT_EGLIBC_BUNDLED_NSS_CONFIG}" = "y" ]; then
avrac@1569
   144
            nss_config="${CT_SRC_DIR}/eglibc-${CT_LIBC_VERSION}/nss/fixed-nsswitch.conf"
avrac@1569
   145
        else
avrac@1569
   146
            nss_config="${CT_EGLIBC_NSS_CONFIG_FILE}"
avrac@1569
   147
        fi
avrac@1569
   148
        CT_TestOrAbort "NSS config file not found!" -n "${nss_config}" -a -f "${nss_config}"
avrac@1569
   149
avrac@1569
   150
        CT_DoExecLog ALL cp "${nss_config}" "${CT_CONFIG_DIR}/nsswitch.config"
avrac@1569
   151
        echo "OPTION_EGLIBC_NSSWITCH_FIXED_CONFIG = ${CT_CONFIG_DIR}/nsswitch.config" \
avrac@1569
   152
            >> "${CT_CONFIG_DIR}/eglibc.config"
avrac@1569
   153
avrac@1569
   154
        if [ "${CT_EGLIBC_BUNDLED_NSS_FUNCTIONS}" = "y" ]; then
avrac@1569
   155
            nss_functions="${CT_SRC_DIR}/eglibc-${CT_LIBC_VERSION}/nss/fixed-nsswitch.functions"
avrac@1569
   156
        else
avrac@1569
   157
            nss_functions="${CT_EGLIBC_NSS_FUNCTIONS_FILE}"
avrac@1569
   158
        fi
avrac@1569
   159
        CT_TestOrAbort "NSS functions file not found!" -n "${nss_functions}" -a -f "${nss_functions}"
avrac@1569
   160
avrac@1569
   161
        CT_DoExecLog ALL cp "${nss_functions}" "${CT_CONFIG_DIR}/nsswitch.functions"
avrac@1569
   162
        echo "OPTION_EGLIBC_NSSWITCH_FIXED_FUNCTIONS = ${CT_CONFIG_DIR}/nsswitch.functions" \
avrac@1569
   163
            >> "${CT_CONFIG_DIR}/eglibc.config"
avrac@1569
   164
    else
avrac@1569
   165
        CT_DoLog DEBUG "Using full-blown nsswitch facility"
avrac@1569
   166
    fi
avrac@1569
   167
avrac@1569
   168
    CT_EndStep
yann@850
   169
}
yann@850
   170
yann@884
   171
# This function installs the eglibc headers needed to build the core compiler
yann@850
   172
do_libc_headers() {
yann@850
   173
    # Instead of doing two time the same actions, headers will
yann@850
   174
    # be installed with start files
yann@850
   175
    :
yann@850
   176
}
yann@850
   177
yann@850
   178
# Build and install start files
yann@850
   179
do_libc_start_files() {
yann@850
   180
    CT_DoStep INFO "Installing C library headers / start files"
yann@850
   181
yann@850
   182
    mkdir -p "${CT_BUILD_DIR}/build-libc-startfiles"
yann@850
   183
    cd "${CT_BUILD_DIR}/build-libc-startfiles"
yann@850
   184
yann@850
   185
    CT_DoLog EXTRA "Configuring C library"
yann@850
   186
avrac@1569
   187
    if [ "${CT_EGLIBC_CUSTOM_CONFIG}" = "y" ]; then
avrac@1569
   188
        CT_DoExecLog ALL cp "${CT_CONFIG_DIR}/eglibc.config" option-groups.config
avrac@1569
   189
    fi
avrac@1569
   190
yann@850
   191
    cross_cc=$(CT_Which "${CT_TARGET}-gcc")
yann@850
   192
    cross_cxx=$(CT_Which "${CT_TARGET}-g++")
yann@850
   193
    cross_ar=$(CT_Which "${CT_TARGET}-ar")
yann@850
   194
    cross_ranlib=$(CT_Which "${CT_TARGET}-ranlib")
yann@850
   195
    
yann@850
   196
    CT_DoLog DEBUG "Using gcc for target: '${cross_cc}'"
yann@850
   197
    CT_DoLog DEBUG "Using g++ for target: '${cross_cxx}'"
yann@850
   198
    CT_DoLog DEBUG "Using ar for target: '${cross_ar}'"
yann@850
   199
    CT_DoLog DEBUG "Using ranlib for target: '${cross_ranlib}'"
yann@850
   200
yann@1123
   201
    BUILD_CC="${CT_BUILD}-gcc"                          \
yann@1123
   202
    CC=${cross_cc}                                      \
yann@1123
   203
    CXX=${cross_cxx}                                    \
yann@1123
   204
    AR=${cross_ar}                                      \
yann@1123
   205
    RANLIB=${cross_ranlib}                              \
yann@1123
   206
    CT_DoExecLog ALL                                    \
yann@1123
   207
    "${CT_SRC_DIR}/eglibc-${CT_LIBC_VERSION}/configure" \
yann@1123
   208
        --prefix=/usr                                   \
yann@1123
   209
        --with-headers="${CT_HEADERS_DIR}"              \
yann@1123
   210
        --build="${CT_BUILD}"                           \
yann@1123
   211
        --host="${CT_TARGET}"                           \
yann@1123
   212
        --disable-profile                               \
yann@1123
   213
        --without-gd                                    \
yann@1123
   214
        --without-cvs                                   \
yann@850
   215
        --enable-add-ons
yann@850
   216
yann@850
   217
    CT_DoLog EXTRA "Installing C library headers"
yann@850
   218
yann@850
   219
    # use the 'install-headers' makefile target to install the
yann@850
   220
    # headers
yann@850
   221
yann@850
   222
    CT_DoExecLog ALL                    \
yann@850
   223
    make install-headers                \
yann@850
   224
         install_root=${CT_SYSROOT_DIR} \
yann@850
   225
         install-bootstrap-headers=yes
yann@850
   226
yann@850
   227
    CT_DoLog EXTRA "Installing C library start files"
yann@850
   228
yann@850
   229
    # there are a few object files needed to link shared libraries,
yann@850
   230
    # which we build and install by hand
yann@850
   231
yann@850
   232
    CT_DoExecLog ALL mkdir -p ${CT_SYSROOT_DIR}/usr/lib
yann@850
   233
    CT_DoExecLog ALL make csu/subdir_lib
yann@850
   234
    CT_DoExecLog ALL cp csu/crt1.o csu/crti.o csu/crtn.o \
yann@850
   235
        ${CT_SYSROOT_DIR}/usr/lib
yann@850
   236
yann@850
   237
    # Finally, 'libgcc_s.so' requires a 'libc.so' to link against.  
yann@850
   238
    # However, since we will never actually execute its code, 
yann@850
   239
    # it doesn't matter what it contains.  So, treating '/dev/null' 
yann@850
   240
    # as a C source file, we produce a dummy 'libc.so' in one step
yann@850
   241
yann@850
   242
    CT_DoExecLog ALL ${cross_cc} -nostdlib -nostartfiles -shared -x c /dev/null -o ${CT_SYSROOT_DIR}/usr/lib/libc.so
yann@850
   243
yann@850
   244
    CT_EndStep
yann@850
   245
}
yann@850
   246
yann@850
   247
# This function builds and install the full glibc
yann@850
   248
do_libc() {
yann@1478
   249
    local -a extra_config
yann@1478
   250
yann@850
   251
    CT_DoStep INFO "Installing C library"
yann@850
   252
yann@850
   253
    mkdir -p "${CT_BUILD_DIR}/build-libc"
yann@850
   254
    cd "${CT_BUILD_DIR}/build-libc"
yann@850
   255
yann@850
   256
    CT_DoLog EXTRA "Configuring C library"
yann@850
   257
avrac@1569
   258
    if [ "${CT_EGLIBC_CUSTOM_CONFIG}" = "y" ]; then
avrac@1569
   259
        CT_DoExecLog ALL cp "${CT_CONFIG_DIR}/eglibc.config" option-groups.config
avrac@1569
   260
    fi
avrac@1569
   261
yann@850
   262
    # Add some default glibc config options if not given by user.
yann@850
   263
    # We don't need to be conditional on wether the user did set different
yann@850
   264
    # values, as they CT_LIBC_GLIBC_EXTRA_CONFIG is passed after extra_config
yann@850
   265
yann@1478
   266
    extra_config+=("--enable-kernel=$(echo ${CT_LIBC_GLIBC_MIN_KERNEL} |sed -r -e 's/^([^.]+\.[^.]+\.[^.]+)(|\.[^.]+)$/\1/;')")
yann@850
   267
yann@850
   268
    case "${CT_THREADS}" in
yann@1478
   269
        nptl)           extra_config+=("--with-__thread" "--with-tls");;
yann@1478
   270
        linuxthreads)   extra_config+=("--with-__thread" "--without-tls" "--without-nptl");;
yann@1478
   271
        none)           extra_config+=("--without-__thread" "--without-nptl")
yann@850
   272
                        case "${CT_LIBC_GLIBC_EXTRA_CONFIG}" in
yann@850
   273
                            *-tls*) ;;
yann@1478
   274
                            *) extra_config+=("--without-tls");;
yann@850
   275
                        esac
yann@850
   276
                        ;;
yann@850
   277
    esac
yann@850
   278
yann@850
   279
    case "${CT_SHARED_LIBS}" in
yann@1478
   280
        y) extra_config+=("--enable-shared");;
yann@1478
   281
        *) extra_config+=("--disable-shared");;
yann@850
   282
    esac
yann@850
   283
yann@850
   284
    case "${CT_ARCH_FLOAT_HW},${CT_ARCH_FLOAT_SW}" in
yann@1478
   285
        y,) extra_config+=("--with-fp");;
yann@1478
   286
        ,y) extra_config+=("--without-fp");;
yann@850
   287
    esac
yann@850
   288
yann@850
   289
    case "$(do_libc_add_ons_list ,)" in
yann@850
   290
        "") ;;
yann@1478
   291
        *)  extra_config+=("--enable-add-ons=$(do_libc_add_ons_list ,)");;
yann@850
   292
    esac
yann@850
   293
yann@850
   294
    extra_cc_args="${extra_cc_args} ${CT_ARCH_ENDIAN_OPT}"
yann@850
   295
yann@850
   296
    cross_cc=$(CT_Which "${CT_TARGET}-gcc")    
yann@850
   297
yann@850
   298
    CT_DoLog DEBUG "Using gcc for target:     '${cross_cc}'"
yann@850
   299
    CT_DoLog DEBUG "Configuring with addons : '$(do_libc_add_ons_list ,)'"
yann@1478
   300
    CT_DoLog DEBUG "Extra config args passed: '${extra_config[*]}'"
yann@850
   301
    CT_DoLog DEBUG "Extra CC args passed    : '${extra_cc_args}'"
yann@850
   302
yann@1041
   303
    BUILD_CC="${CT_BUILD}-gcc"                                      \
yann@1552
   304
    CFLAGS="${CT_TARGET_CFLAGS} ${CT_LIBC_GLIBC_EXTRA_CFLAGS} -O2"  \
yann@850
   305
    CC="${CT_TARGET}-gcc ${CT_LIBC_EXTRA_CC_ARGS} ${extra_cc_args}" \
yann@850
   306
    AR=${CT_TARGET}-ar                                              \
yann@850
   307
    RANLIB=${CT_TARGET}-ranlib                                      \
yann@850
   308
    CT_DoExecLog ALL                                                \
yann@1123
   309
    "${CT_SRC_DIR}/eglibc-${CT_LIBC_VERSION}/configure"             \
yann@850
   310
        --prefix=/usr                                               \
yann@850
   311
        --with-headers="${CT_HEADERS_DIR}"                          \
yann@1041
   312
        --build=${CT_BUILD}                                         \
yann@850
   313
        --host=${CT_TARGET}                                         \
yann@850
   314
        --disable-profile                                           \
yann@850
   315
        --without-gd                                                \
yann@850
   316
        --without-cvs                                               \
yann@1478
   317
        "${extra_config[@]}"                                        \
yann@850
   318
        ${CT_LIBC_GLIBC_EXTRA_CONFIG}
yann@850
   319
    
yann@850
   320
    CT_DoLog EXTRA "Building C library"
yann@850
   321
yann@1328
   322
    # eglibc build hacks
yann@1328
   323
    # http://sourceware.org/ml/crossgcc/2008-10/msg00068.html
yann@1328
   324
    case "${CT_ARCH},${CT_ARCH_CPU}" in
yann@1328
   325
        powerpc,8??)
yann@1328
   326
            CT_DoLog DEBUG "Activating support for memset on broken ppc-8xx (CPU15 erratum)"
yann@1328
   327
            EGLIBC_BUILD_ASFLAGS="-DBROKEN_PPC_8xx_CPU15";;
yann@1328
   328
    esac
yann@1328
   329
yann@1328
   330
    CT_DoExecLog ALL make ASFLAGS="${EGLIBC_BUILD_ASFLAGS}"
yann@850
   331
yann@850
   332
    CT_DoLog EXTRA "Installing C library"
yann@850
   333
yann@850
   334
    CT_DoExecLog ALL make install install_root="${CT_SYSROOT_DIR}"
yann@850
   335
yann@850
   336
    CT_EndStep
yann@850
   337
}
yann@850
   338
yann@850
   339
# This function finishes the glibc install
yann@850
   340
do_libc_finish() {
yann@850
   341
    # Nothing to be done for eglibc
yann@850
   342
    :
yann@850
   343
}
yann@850
   344
yann@850
   345
# Build up the addons list, separated with $1
yann@850
   346
do_libc_add_ons_list() {
yann@850
   347
    local sep="$1"
yann@850
   348
    local addons_list=$(echo "${CT_LIBC_ADDONS_LIST//,/${sep}}" |tr -s ,)
yann@850
   349
    case "${CT_THREADS}" in
yann@850
   350
        none)   ;;
yann@850
   351
        *)      addons_list="${addons_list}${sep}${CT_THREADS}";;
yann@850
   352
    esac
yann@850
   353
    [ "${CT_LIBC_GLIBC_USE_PORTS}" = "y" ] && addons_list="${addons_list}${sep}ports"
yann@850
   354
    addons_list="${addons_list%%${sep}}"
yann@850
   355
    echo "${addons_list##${sep}}"
yann@850
   356
}