diff options
| author | bernard <[email protected]> | 2017-10-15 22:41:59 +0800 |
|---|---|---|
| committer | bernard <[email protected]> | 2017-10-15 22:41:59 +0800 |
| commit | 5c7b16d00bdb536a694e6e31a2e0a1c33cb9dcb9 (patch) | |
| tree | 5da5e3404e1241b65e90089c4c370b40130df832 /components/libc/compilers | |
| parent | b27c7e482648535760e012cd6f1afef1d800e2d2 (diff) | |
[libc] Update libc.
1. Add POSIX termios implementation;
2. Add POSIX signals implementation;
3. Add stdio for each libc.
Diffstat (limited to 'components/libc/compilers')
26 files changed, 711 insertions, 337 deletions
diff --git a/components/libc/compilers/armlibc/libc.c b/components/libc/compilers/armlibc/libc.c new file mode 100644 index 0000000000..d3a4ad06d0 --- /dev/null +++ b/components/libc/compilers/armlibc/libc.c @@ -0,0 +1,59 @@ +/* + * File : libc.c + * Brief : armcc libc initialization + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard the first version + */ +#include <stdio.h> +#include <stdlib.h> + +#include <rtthread.h> + +#include "libc.h" + +#ifdef RT_USING_PTHREADS +#include <pthread.h> +#endif + +int libc_system_init(void) +{ +#if defined(RT_USING_DFS) & defined(RT_USING_DFS_DEVFS) + rt_device_t dev_console; + + dev_console = rt_console_get_device(); + if (dev_console) + { + #if defined(RT_USING_POSIX_STDIN) + libc_stdio_set_console(dev_console->parent.name, O_RDWR); + #else + libc_stdio_set_console(dev_console->parent.name, O_WRONLY); + #endif + } +#endif + +#if defined RT_USING_PTHREADS && !defined RT_USING_COMPONENTS_INIT + pthread_system_init(); +#endif + + return 0; +} +INIT_COMPONENT_EXPORT(libc_system_init); diff --git a/components/libc/compilers/armlibc/libc.h b/components/libc/compilers/armlibc/libc.h new file mode 100644 index 0000000000..5e9f68218d --- /dev/null +++ b/components/libc/compilers/armlibc/libc.h @@ -0,0 +1,37 @@ +/* + * File : libc.h + * Brief : armcc libc header file + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard the first version + */ +#ifndef __RTT_LIBC_H__ +#define __RTT_LIBC_H__ + +#include <stddef.h> + +int libc_system_init(void); + +int libc_stdio_set_console(const char* device_name, int mode); +int libc_stdio_read (void *buffer, size_t size); +int libc_stdio_write(void *buffer, size_t size); + +#endif diff --git a/components/libc/compilers/armlibc/mem_std.c b/components/libc/compilers/armlibc/mem_std.c index 56aa525df2..5da5bb6c6c 100644 --- a/components/libc/compilers/armlibc/mem_std.c +++ b/components/libc/compilers/armlibc/mem_std.c @@ -32,7 +32,7 @@ RTM_EXPORT(realloc); void *calloc(rt_size_t nelem, rt_size_t elsize) { - return rt_calloc(nelem, elsize); + return rt_calloc(nelem, elsize); } RTM_EXPORT(calloc); diff --git a/components/libc/compilers/armlibc/stdio.c b/components/libc/compilers/armlibc/stdio.c new file mode 100644 index 0000000000..8c9c99b3ad --- /dev/null +++ b/components/libc/compilers/armlibc/stdio.c @@ -0,0 +1,70 @@ +/* + * File : stdio.c + * Brief : stdio/console + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard implement stdio for armcc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <rtthread.h> +#include "libc.h" + +#if defined(RT_USING_DFS) && defined(RT_USING_DFS_DEVFS) +#include <dfs_posix.h> + +#define STDIO_DEVICE_NAME_MAX 32 + +static int std_fd = -1; +int libc_stdio_set_console(const char* device_name, int mode) +{ + int fd; + char name[STDIO_DEVICE_NAME_MAX]; + + snprintf(name, sizeof(name) - 1, "/dev/%s", device_name); + name[STDIO_DEVICE_NAME_MAX - 1] = '\0'; + + fd = open(name, mode, 0); + if (fd >= 0) + { + if (std_fd >= 0) + { + close(std_fd); + } + std_fd = fd; + } + + return std_fd; +} + +int libc_stdio_read(void *buffer, size_t size) +{ + return read(std_fd, buffer, size); +} + +int libc_stdio_write(void *buffer, size_t size) +{ + return write(std_fd, buffer, size); +} +#endif diff --git a/components/libc/compilers/armlibc/stubs.c b/components/libc/compilers/armlibc/stubs.c index 395e51ecda..0de8aacb3c 100644 --- a/components/libc/compilers/armlibc/stubs.c +++ b/components/libc/compilers/armlibc/stubs.c @@ -2,12 +2,22 @@ * File : stubs.c * Brief : reimplement some basic functions of arm standard c library * - * This file is part of Device File System in RT-Thread RTOS - * COPYRIGHT (C) 2004-2012, RT-Thread Development Team + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE. + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Change Logs: * Date Author Notes @@ -28,10 +38,10 @@ #pragma import(__use_no_semihosting_swi) -/* TODO: Standard IO device handles. */ -#define STDIN 1 -#define STDOUT 2 -#define STDERR 3 +/* Standard IO device handles. */ +#define STDIN 0 +#define STDOUT 1 +#define STDERR 2 /* Standard IO device name defines. */ const char __stdin_name[] = "STDIN"; @@ -94,7 +104,7 @@ FILEHANDLE _sys_open(const char *name, int openmode) if (fd < 0) return -1; else - return fd + STDERR + 1; + return fd; #endif } @@ -103,21 +113,36 @@ int _sys_close(FILEHANDLE fh) #ifndef RT_USING_DFS return 0; #else - if (fh < STDERR) - return 0; + if (fh <= STDERR) return 0; - return close(fh - STDERR - 1); + return close(fh); #endif } -/** - * read data +/* + * Read from a file. Can return: + * - zero if the read was completely successful + * - the number of bytes _not_ read, if the read was partially successful + * - the number of bytes not read, plus the top bit set (0x80000000), if + * the read was partially successful due to end of file + * - -1 if some error other than EOF occurred * - * @param fh - file handle - * @param buf - buffer to save read data - * @param len - max length of data buffer - * @param mode - useless, for historical reasons - * @return The number of bytes not read. + * It is also legal to signal EOF by returning no data but + * signalling no error (i.e. the top-bit-set mechanism need never + * be used). + * + * So if (for example) the user is trying to read 8 bytes at a time + * from a file in which only 5 remain, this routine can do three + * equally valid things: + * + * - it can return 0x80000003 (3 bytes not read due to EOF) + * - OR it can return 3 (3 bytes not read), and then return + * 0x80000008 (8 bytes not read due to EOF) on the next attempt + * - OR it can return 3 (3 bytes not read), and then return + * 8 (8 bytes not read, meaning 0 read, meaning EOF) on the next + * attempt + * + * `mode' exists for historical reasons and must be ignored. */ int _sys_read(FILEHANDLE fh, unsigned char *buf, unsigned len, int mode) { @@ -127,8 +152,13 @@ int _sys_read(FILEHANDLE fh, unsigned char *buf, unsigned len, int mode) if (fh == STDIN) { - /* TODO */ - return 0; +#ifdef RT_USING_POSIX_STDIN + size = libc_stdio_read(buf, len); + return len - size; +#else + /* no stdin */ + return -1; +#endif } if ((fh == STDOUT) || (fh == STDERR)) @@ -137,7 +167,7 @@ int _sys_read(FILEHANDLE fh, unsigned char *buf, unsigned len, int mode) #ifndef RT_USING_DFS return 0; #else - size = read(fh - STDERR - 1, buf, len); + size = read(fh, buf, len); if (size >= 0) return len - size; else @@ -145,14 +175,10 @@ int _sys_read(FILEHANDLE fh, unsigned char *buf, unsigned len, int mode) #endif } -/** - * write data - * - * @param fh - file handle - * @param buf - data buffer - * @param len - buffer length - * @param mode - useless, for historical reasons - * @return a positive number representing the number of characters not written. +/* + * Write to a file. Returns 0 on success, negative on error, and + * the number of characters _not_ written on partial success. + * `mode' exists for historical reasons and must be ignored. */ int _sys_write(FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode) { @@ -165,22 +191,27 @@ int _sys_write(FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode) #ifndef RT_USING_CONSOLE return 0; #else - rt_device_t console_device; - - console_device = rt_console_get_device(); - if (console_device != 0) rt_device_write(console_device, 0, buf, len); +#ifdef RT_USING_POSIX_STDIN + size = libc_stdio_write(buf, len); + return len - size; +#else + if (rt_console_get_device()) + { + rt_device_write(rt_console_get_device(), -1, buf, len); + return 0; + } - return 0; + return -1; +#endif #endif } - if (fh == STDIN) - return -1; + if (fh == STDIN) return -1; #ifndef RT_USING_DFS return 0; #else - size = write(fh - STDERR - 1, buf, len); + size = write(fh, buf, len); if (size >= 0) return len - size; else @@ -188,11 +219,9 @@ int _sys_write(FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode) #endif } -/** - * put he file pointer at offset pos from the beginning of the file. - * - * @param pos - offset - * @return the current file position, or -1 on failed +/* + * Move the file position to a given offset from the file start. + * Returns >=0 on success, <0 on failure. */ int _sys_seek(FILEHANDLE fh, long pos) { @@ -204,7 +233,7 @@ int _sys_seek(FILEHANDLE fh, long pos) #else /* position is relative to the start of file fh */ - return lseek(fh - STDERR - 1, pos, 0); + return lseek(fh, pos, 0); #endif } @@ -285,7 +314,15 @@ int fputc(int c, FILE *f) return 1; } -int fgetc(FILE *f) { - return -1; +int fgetc(FILE *f) +{ + char ch; + +#ifdef RT_USING_POSIX_STDIN + if (libc_stdio_read(&ch, 1) == 1) + return ch; +#endif + + return -1; } #endif diff --git a/components/libc/compilers/armlibc/sys/errno.h b/components/libc/compilers/armlibc/sys/errno.h index 0aba5f5e19..8ee115ed04 100644 --- a/components/libc/compilers/armlibc/sys/errno.h +++ b/components/libc/compilers/armlibc/sys/errno.h @@ -1,80 +1,6 @@ #ifndef SYS_ERRNO_H__ #define SYS_ERRNO_H__ -#ifdef RT_USING_DFS - -#include <dfs_def.h> - -/* using device error codes */ -#define ENOENT DFS_STATUS_ENOENT -#define EIO DFS_STATUS_EIO -#define ENXIO DFS_STATUS_ENXIO -#define EBADF DFS_STATUS_EBADF -#define EAGAIN DFS_STATUS_EAGAIN -#define ENOMEM DFS_STATUS_ENOMEM -#define EBUSY DFS_STATUS_EBUSY -#define EEXIST DFS_STATUS_EEXIST -#define EXDEV DFS_STATUS_EXDEV -#define ENODEV DFS_STATUS_ENODEV -#define ENOTDIR DFS_STATUS_ENOTDIR -#define EISDIR DFS_STATUS_EISDIR -#define EINVAL DFS_STATUS_EINVAL -#define ENOSPC DFS_STATUS_ENOSPC -#define EROFS DFS_STATUS_EROFS -#define ENOSYS DFS_STATUS_ENOSYS -#define ENOTEMPTY DFS_STATUS_ENOTEMPTY - -#else - -/* error codes */ -#define ENOENT 2 /* No such file or directory */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define EBADF 9 /* Bad file number */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* no memory */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENOSPC 28 /* No space left on device */ -#define EROFS 30 /* Read-only file system */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ - -#endif - -#define EPERM 1 /* Not super-user */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENFILE 23 /* Too many open files in system */ -#define ERANGE 34 /* Math result not representable */ -#define EDEADLK 45 /* Deadlock condition */ -#define EBADMSG 77 /* Trying to read unreadable message */ -#define EMSGSIZE 90 /* Message too long */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ETIMEDOUT 116 /* Connection timed out */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define ENOTSUP 134 /* Not supported */ -#define ENSRNOTFOUND 163 /* Domain name not found */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ +#include <rtthread.h> #endif diff --git a/components/libc/compilers/armlibc/sys/unistd.h b/components/libc/compilers/armlibc/sys/unistd.h index e1e0dc904c..38ba8b5072 100644 --- a/components/libc/compilers/armlibc/sys/unistd.h +++ b/components/libc/compilers/armlibc/sys/unistd.h @@ -6,31 +6,31 @@ #ifdef RT_USING_DFS #include <dfs_posix.h> #else -#define _FREAD 0x0001 /* read enabled */ -#define _FWRITE 0x0002 /* write enabled */ -#define _FAPPEND 0x0008 /* append (writes guaranteed at the end) */ -#define _FMARK 0x0010 /* internal; mark during gc() */ -#define _FDEFER 0x0020 /* internal; defer for next gc pass */ -#define _FASYNC 0x0040 /* signal pgrp when data ready */ -#define _FSHLOCK 0x0080 /* BSD flock() shared lock present */ -#define _FEXLOCK 0x0100 /* BSD flock() exclusive lock present */ -#define _FCREAT 0x0200 /* open with file create */ -#define _FTRUNC 0x0400 /* open with truncation */ -#define _FEXCL 0x0800 /* error on open if file exists */ -#define _FNBIO 0x1000 /* non blocking I/O (sys5 style) */ -#define _FSYNC 0x2000 /* do all writes synchronously */ -#define _FNONBLOCK 0x4000 /* non blocking I/O (POSIX style) */ -#define _FNDELAY _FNONBLOCK /* non blocking I/O (4.2 style) */ -#define _FNOCTTY 0x8000 /* don't assign a ctty on this open */ +#define _FREAD 0x0001 /* read enabled */ +#define _FWRITE 0x0002 /* write enabled */ +#define _FAPPEND 0x0008 /* append (writes guaranteed at the end) */ +#define _FMARK 0x0010 /* internal; mark during gc() */ +#define _FDEFER 0x0020 /* internal; defer for next gc pass */ +#define _FASYNC 0x0040 /* signal pgrp when data ready */ +#define _FSHLOCK 0x0080 /* BSD flock() shared lock present */ +#define _FEXLOCK 0x0100 /* BSD flock() exclusive lock present */ +#define _FCREAT 0x0200 /* open with file create */ +#define _FTRUNC 0x0400 /* open with truncation */ +#define _FEXCL 0x0800 /* error on open if file exists */ +#define _FNBIO 0x1000 /* non blocking I/O (sys5 style) */ +#define _FSYNC 0x2000 /* do all writes synchronously */ +#define _FNONBLOCK 0x4000 /* non blocking I/O (POSIX style) */ +#define _FNDELAY _FNONBLOCK /* non blocking I/O (4.2 style) */ +#define _FNOCTTY 0x8000 /* don't assign a ctty on this open */ -#define O_RDONLY 0 /* +1 == FREAD */ -#define O_WRONLY 1 /* +1 == FWRITE */ -#define O_RDWR 2 /* +1 == FREAD|FWRITE */ -#define O_APPEND _FAPPEND -#define O_CREAT _FCREAT -#define O_TRUNC _FTRUNC -#define O_EXCL _FEXCL -#define O_SYNC _FSYNC +#define O_RDONLY 0 /* +1 == FREAD */ +#define O_WRONLY 1 /* +1 == FWRITE */ +#define O_RDWR 2 /* +1 == FREAD|FWRITE */ +#define O_APPEND _FAPPEND +#define O_CREAT _FCREAT +#define O_TRUNC _FTRUNC +#define O_EXCL _FEXCL +#define O_SYNC _FSYNC #endif #endif /* _SYS_UNISTD_H */ diff --git a/components/libc/compilers/dlib/libc.c b/components/libc/compilers/dlib/libc.c new file mode 100644 index 0000000000..ba998e9747 --- /dev/null +++ b/components/libc/compilers/dlib/libc.c @@ -0,0 +1,59 @@ +/* + * File : libc.c + * Brief : iar dlib initialization + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard the first version + */ +#include <stdio.h> +#include <stdlib.h> + +#include <rtthread.h> + +#include "libc.h" + +#ifdef RT_USING_PTHREADS +#include <pthread.h> +#endif + +int libc_system_init(void) +{ +#if defined(RT_USING_DFS) & defined(RT_USING_DFS_DEVFS) + rt_device_t dev_console; + + dev_console = rt_console_get_device(); + if (dev_console) + { + #if defined(RT_USING_POSIX_STDIN) + libc_stdio_set_console(dev_console->parent.name, O_RDWR); + #else + libc_stdio_set_console(dev_console->parent.name, O_WRONLY); + #endif + } +#endif + +#if defined RT_USING_PTHREADS && !defined RT_USING_COMPONENTS_INIT + pthread_system_init(); +#endif + + return 0; +} +INIT_COMPONENT_EXPORT(libc_system_init); diff --git a/components/libc/compilers/dlib/libc.h b/components/libc/compilers/dlib/libc.h new file mode 100644 index 0000000000..db571d2ee1 --- /dev/null +++ b/components/libc/compilers/dlib/libc.h @@ -0,0 +1,38 @@ +/* + * File : libc.h + * Brief : iar dlib header file + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard the first version + */ + +#ifndef __RTT_LIBC_H__ +#define __RTT_LIBC_H__ + +#include <stddef.h> + +int libc_system_init(void); + +int libc_stdio_set_console(const char* device_name, int mode); +int libc_stdio_read (void *buffer, size_t size); +int libc_stdio_write(const void *buffer, size_t size); + +#endif diff --git a/components/libc/compilers/dlib/stdio.c b/components/libc/compilers/dlib/stdio.c new file mode 100644 index 0000000000..24e421f2b3 --- /dev/null +++ b/components/libc/compilers/dlib/stdio.c @@ -0,0 +1,70 @@ +/* + * File : stdio.c + * Brief : stdio/console + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard implement stdio for IAR dlib. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <rtthread.h> +#include "libc.h" + +#if defined(RT_USING_DFS) && defined(RT_USING_DFS_DEVFS) +#include <dfs_posix.h> + +#define STDIO_DEVICE_NAME_MAX 32 + +static int std_fd = -1; +int libc_stdio_set_console(const char* device_name, int mode) +{ + int fd; + char name[STDIO_DEVICE_NAME_MAX]; + + snprintf(name, sizeof(name) - 1, "/dev/%s", device_name); + name[STDIO_DEVICE_NAME_MAX - 1] = '\0'; + + fd = open(name, mode, 0); + if (fd >= 0) + { + if (std_fd >= 0) + { + close(std_fd); + } + std_fd = fd; + } + + return std_fd; +} + +int libc_stdio_read(void *buffer, size_t size) +{ + return read(std_fd, buffer, size); +} + +int libc_stdio_write(const void *buffer, size_t size) +{ + return write(std_fd, buffer, size); +} +#endif diff --git a/components/libc/compilers/dlib/sys/errno.h b/components/libc/compilers/dlib/sys/errno.h index a8e09ffd24..072892edc1 100644 --- a/components/libc/compilers/dlib/sys/errno.h +++ b/components/libc/compilers/dlib/sys/errno.h @@ -1,80 +1,7 @@ #ifndef SYS_ERRNO_H__ #define SYS_ERRNO_H__ -#ifdef RT_USING_DFS +#include <rtthread.h> -#include <dfs_def.h> - -/* using device error codes */ -#define ENOENT DFS_STATUS_ENOENT -#define EIO DFS_STATUS_EIO -#define ENXIO DFS_STATUS_ENXIO -#define EBADF DFS_STATUS_EBADF -#define EAGAIN DFS_STATUS_EAGAIN -#define ENOMEM DFS_STATUS_ENOMEM -#define EBUSY DFS_STATUS_EBUSY -#define EEXIST DFS_STATUS_EEXIST -#define EXDEV DFS_STATUS_EXDEV -#define ENODEV DFS_STATUS_ENODEV -#define ENOTDIR DFS_STATUS_ENOTDIR -#define EISDIR DFS_STATUS_EISDIR -#define EINVAL DFS_STATUS_EINVAL -#define ENOSPC DFS_STATUS_ENOSPC -#define EROFS DFS_STATUS_EROFS -#define ENOSYS DFS_STATUS_ENOSYS -#define ENOTEMPTY DFS_STATUS_ENOTEMPTY - -#else - -/* error codes */ -#define ENOENT 2 /* No such file or directory */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define EBADF 9 /* Bad file number */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* no memory */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENOSPC 28 /* No space left on device */ -#define EROFS 30 /* Read-only file system */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ - -#endif - -#define EPERM 1 /* Not super-user */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENFILE 23 /* Too many open files in system */ -#define ERANGE 34 /* Math result not representable */ -#define EDEADLK 45 /* Deadlock condition */ -#define EBADMSG 77 /* Trying to read unreadable message */ -#define EMSGSIZE 90 /* Message too long */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ETIMEDOUT 116 /* Connection timed out */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define ENOTSUP 134 /* Not supported */ -#define ENSRNOTFOUND 163 /* Domain name not found */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ #endif diff --git a/components/libc/compilers/dlib/syscall_close.c b/components/libc/compilers/dlib/syscall_close.c index c2bb0b63d6..5792bb3806 100644 --- a/components/libc/compilers/dlib/syscall_close.c +++ b/components/libc/compilers/dlib/syscall_close.c @@ -36,7 +36,7 @@ int __close(int handle) return _LLIO_ERROR; #ifdef RT_USING_DFS - return close(handle - _LLIO_STDERR - 1); + return close(handle); #else return 0; #endif diff --git a/components/libc/compilers/dlib/syscall_lseek.c b/components/libc/compilers/dlib/syscall_lseek.c index 23d509817e..950ba52f65 100644 --- a/components/libc/compilers/dlib/syscall_lseek.c +++ b/components/libc/compilers/dlib/syscall_lseek.c @@ -36,7 +36,7 @@ long __lseek(int handle, long offset, int whence) return _LLIO_ERROR; #ifdef RT_USING_DFS - return lseek(handle - _LLIO_STDERR - 1, offset, whence); + return lseek(handle, offset, whence); #else return _LLIO_ERROR; #endif diff --git a/components/libc/compilers/dlib/syscall_mem.c b/components/libc/compilers/dlib/syscall_mem.c index 10eb298b9c..05e79f50b2 100644 --- a/components/libc/compilers/dlib/syscall_mem.c +++ b/components/libc/compilers/dlib/syscall_mem.c @@ -35,7 +35,7 @@ void *realloc(void *rmem, rt_size_t newsize) void *calloc(rt_size_t nelem, rt_size_t elsize) { - return rt_calloc(nelem, elsize); + return rt_calloc(nelem, elsize); } void free(void *rmem) diff --git a/components/libc/compilers/dlib/syscall_open.c b/components/libc/compilers/dlib/syscall_open.c index 95fa43b9c6..6194707549 100644 --- a/components/libc/compilers/dlib/syscall_open.c +++ b/components/libc/compilers/dlib/syscall_open.c @@ -33,56 +33,56 @@ int __open(const char *filename, int mode) { #ifndef RT_USING_DFS - return -1; + return _LLIO_ERROR; #else int handle; int open_mode = O_RDONLY; - + if (mode & _LLIO_CREAT) { open_mode |= O_CREAT; - + /* Check what we should do with it if it exists. */ if (mode & _LLIO_APPEND) { /* Append to the existing file. */ open_mode |= O_APPEND; } - + if (mode & _LLIO_TRUNC) { /* Truncate the existsing file. */ open_mode |= O_TRUNC; } } - + if (mode & _LLIO_TEXT) { /* we didn't support text mode */ } - + switch (mode & _LLIO_RDWRMASK) { case _LLIO_RDONLY: break; - + case _LLIO_WRONLY: open_mode |= O_WRONLY; break; - + case _LLIO_RDWR: /* The file should be opened for both reads and writes. */ open_mode |= O_RDWR; break; - + default: - return -1; + return _LLIO_ERROR; } - + handle = open(filename, open_mode, 0); if (handle < 0) - return -1; - - return handle + _LLIO_STDERR + 1; + return _LLIO_ERROR; + + return handle; #endif } diff --git a/components/libc/compilers/dlib/syscall_read.c b/components/libc/compilers/dlib/syscall_read.c index aa13654189..9dcaa9df65 100644 --- a/components/libc/compilers/dlib/syscall_read.c +++ b/components/libc/compilers/dlib/syscall_read.c @@ -27,6 +27,7 @@ #include <dfs_posix.h> #endif #include <yfuns.h> +#include "libc.h" #pragma module_name = "?__read" size_t __read(int handle, unsigned char *buf, size_t len) @@ -37,8 +38,11 @@ size_t __read(int handle, unsigned char *buf, size_t len) if (handle == _LLIO_STDIN) { - /* TODO */ - return 0; +#ifdef RT_USING_POSIX_STDIN + return libc_stdio_read(buf, len); +#else + return _LLIO_ERROR; +#endif } if ((handle == _LLIO_STDOUT) || (handle == _LLIO_STDERR)) @@ -47,7 +51,7 @@ size_t __read(int handle, unsigned char *buf, size_t len) #ifndef RT_USING_DFS return _LLIO_ERROR; #else - size = read(handle - _LLIO_STDERR - 1, buf, len); + size = read(handle, buf, len); return size; #endif } diff --git a/components/libc/compilers/dlib/syscall_write.c b/components/libc/compilers/dlib/syscall_write.c index a7140b9818..e2cb04000b 100644 --- a/components/libc/compilers/dlib/syscall_write.c +++ b/components/libc/compilers/dlib/syscall_write.c @@ -27,6 +27,7 @@ #include <dfs_posix.h> #endif #include <yfuns.h> +#include "libc.h" #pragma module_name = "?__write" @@ -41,6 +42,10 @@ size_t __write(int handle, const unsigned char *buf, size_t len) #ifndef RT_USING_CONSOLE return _LLIO_ERROR; #else + +#ifdef RT_USING_POSIX_STDIN + return libc_stdio_write((void*)buf, len); +#else rt_device_t console_device; console_device = rt_console_get_device(); @@ -48,14 +53,15 @@ size_t __write(int handle, const unsigned char *buf, size_t len) return len; #endif +#endif } - if (handle == _LLIO_STDIN) return -1; + if (handle == _LLIO_STDIN) return _LLIO_ERROR; #ifndef RT_USING_DFS return _LLIO_ERROR; #else - size = write(handle - _LLIO_STDERR - 1, buf, len); + size = write(handle, buf, len); return size; #endif } diff --git a/components/libc/compilers/dlib/unistd.h b/components/libc/compilers/dlib/unistd.h new file mode 100644 index 0000000000..d67f8fb6f2 --- /dev/null +++ b/components/libc/compilers/dlib/unistd.h @@ -0,0 +1,6 @@ +#ifndef _UNISTD_H_ +#define _UNISTD_H_ + +# include "sys/unistd.h" + +#endif /* _UNISTD_H_ */ diff --git a/components/libc/compilers/newlib/libc.c b/components/libc/compilers/newlib/libc.c index 8f97e1c8b4..c06ded705e 100644 --- a/components/libc/compilers/newlib/libc.c +++ b/components/libc/compilers/newlib/libc.c @@ -1,52 +1,60 @@ +/* + * File : libc.c + * Brief : gcc libc header file + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard the first version + */ #include <rtthread.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/time.h> + #include "libc.h" #ifdef RT_USING_PTHREADS #include <pthread.h> #endif -#ifdef RT_USING_DFS -#include <dfs_posix.h> - -#ifdef RT_USING_DFS_DEVFS -#include <devfs.h> -#endif - -#endif - int libc_system_init(void) { #ifdef RT_USING_DFS - int fd; - struct rt_device *console_dev; - -#ifndef RT_USING_DFS_DEVFS -#error Please enable devfs by defining RT_USING_DFS_DEVFS in rtconfig.h -#endif + rt_device_t dev_console; - console_dev = rt_console_get_device(); - if (console_dev) + dev_console = rt_console_get_device(); + if (dev_console) { - /* initialize console device */ - rt_console_init(console_dev->parent.name); - - /* open console as stdin/stdout/stderr */ - fd = open("/dev/console", O_RDONLY, 0); /* for stdin */ - fd = open("/dev/console", O_WRONLY, 0); /* for stdout */ - fd = open("/dev/console", O_WRONLY, 0); /* for stderr */ - - /* skip warning */ - fd = fd; + #if defined(RT_USING_DFS_DEVFS) && defined(RT_USING_POSIX_STDIN) + libc_stdio_set_console(dev_console->parent.name, O_RDWR); + #else + libc_stdio_set_console(dev_console->parent.name, O_WRONLY); + #endif } #endif /* set PATH and HOME */ putenv("PATH=/bin"); putenv("HOME=/home"); + #if defined RT_USING_PTHREADS && !defined RT_USING_COMPONENTS_INIT pthread_system_init(); #endif diff --git a/components/libc/compilers/newlib/libc.h b/components/libc/compilers/newlib/libc.h index a4f342df33..7cab52a11f 100644 --- a/components/libc/compilers/newlib/libc.h +++ b/components/libc/compilers/newlib/libc.h @@ -1,3 +1,28 @@ +/* + * File : libc.h + * Brief : gcc libc header file + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard the first version + */ #ifndef __RTT_LIBC_H__ #define __RTT_LIBC_H__ @@ -12,6 +37,7 @@ #define NANOSECOND_PER_TICK (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND) int libc_system_init(void); +int libc_stdio_set_console(const char* device_name, int mode); /* some time related function */ int libc_set_time(const struct timespec *time); diff --git a/components/libc/compilers/newlib/libc_sym.c b/components/libc/compilers/newlib/libc_sym.c deleted file mode 100644 index 48e488f5d8..0000000000 --- a/components/libc/compilers/newlib/libc_sym.c +++ /dev/null @@ -1,47 +0,0 @@ -#include <rtthread.h> -#include <rtm.h> - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -RTM_EXPORT(strcpy); -RTM_EXPORT(strncpy); -RTM_EXPORT(strlen); -RTM_EXPORT(strcat); -RTM_EXPORT(strstr); -RTM_EXPORT(strchr); -RTM_EXPORT(strcmp); -RTM_EXPORT(strtol); -RTM_EXPORT(strtoul); -RTM_EXPORT(strncmp); - -RTM_EXPORT(memcpy); -RTM_EXPORT(memcmp); -RTM_EXPORT(memmove); -RTM_EXPORT(memset); -RTM_EXPORT(memchr); - -RTM_EXPORT(putchar); -RTM_EXPORT(puts); -RTM_EXPORT(printf); -RTM_EXPORT(sprintf); -RTM_EXPORT(snprintf); - -RTM_EXPORT(fwrite); - -#include <time.h> -RTM_EXPORT(localtime); -RTM_EXPORT(time); - -#include <setjmp.h> -RTM_EXPORT(longjmp); -RTM_EXPORT(setjmp); - -RTM_EXPORT(exit); -RTM_EXPORT(abort); - -RTM_EXPORT(rand); - -#include <assert.h> -RTM_EXPORT(__assert_func); diff --git a/components/libc/compilers/newlib/libc_syms.c b/components/libc/compilers/newlib/libc_syms.c new file mode 100644 index 0000000000..ed8686e5dd --- /dev/null +++ b/components/libc/compilers/newlib/libc_syms.c @@ -0,0 +1,72 @@ +/* + * File : libc_syms.c + * Brief : exported symbols for libc. + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard the first version + */ +#include <rtthread.h> +#include <rtm.h> + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +RTM_EXPORT(strcpy); +RTM_EXPORT(strncpy); +RTM_EXPORT(strlen); +RTM_EXPORT(strcat); +RTM_EXPORT(strstr); +RTM_EXPORT(strchr); +RTM_EXPORT(strcmp); +RTM_EXPORT(strtol); +RTM_EXPORT(strtoul); +RTM_EXPORT(strncmp); + +RTM_EXPORT(memcpy); +RTM_EXPORT(memcmp); +RTM_EXPORT(memmove); +RTM_EXPORT(memset); +RTM_EXPORT(memchr); + +RTM_EXPORT(putchar); +RTM_EXPORT(puts); +RTM_EXPORT(printf); +RTM_EXPORT(sprintf); +RTM_EXPORT(snprintf); + +RTM_EXPORT(fwrite); + +#include <time.h> +RTM_EXPORT(localtime); +RTM_EXPORT(time); + +#include <setjmp.h> +RTM_EXPORT(longjmp); +RTM_EXPORT(setjmp); + +RTM_EXPORT(exit); +RTM_EXPORT(abort); + +RTM_EXPORT(rand); + +#include <assert.h> +RTM_EXPORT(__assert_func); diff --git a/components/libc/compilers/newlib/stdio.c b/components/libc/compilers/newlib/stdio.c new file mode 100644 index 0000000000..276e68050c --- /dev/null +++ b/components/libc/compilers/newlib/stdio.c @@ -0,0 +1,85 @@ +/* + * File : stdio.c + * Brief : stdio for newlib + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard the first version + */ +#include <stdio.h> +#include <stdlib.h> + +#include <rtthread.h> +#include "libc.h" + +#define STDIO_DEVICE_NAME_MAX 32 + +static FILE* std_console = NULL; + +int libc_stdio_set_console(const char* device_name, int mode) +{ + FILE *fp; + char name[STDIO_DEVICE_NAME_MAX]; + char *file_mode; + + snprintf(name, sizeof(name) - 1, "/dev/%s", device_name); + name[STDIO_DEVICE_NAME_MAX - 1] = '\0'; + + if (mode == O_RDWR) file_mode = "r+"; + else if (mode == O_WRONLY) file_mode = "wb"; + else if (mode == O_RDONLY) file_mode = "rb"; + + fp = fopen(name, file_mode); + if (fp) + { + setvbuf(fp, NULL, _IONBF, 0); + + if (std_console) + { + fclose(std_console); + std_console = NULL; + } + std_console = fp; + + if (mode == O_RDWR) + { + _GLOBAL_REENT->_stdin = std_console; + } + else + { + _GLOBAL_REENT->_stdin = NULL; + } + + if (mode == O_RDONLY) + { + _GLOBAL_REENT->_stdout = NULL; + _GLOBAL_REENT->_stderr = NULL; + } + else + { + _GLOBAL_REENT->_stdout = std_console; + _GLOBAL_REENT->_stderr = std_console; + } + + _GLOBAL_REENT->__sdidinit = 1; + } + + return fileno(std_console); +} diff --git a/components/libc/compilers/newlib/sys/fcntl.h b/components/libc/compilers/newlib/sys/fcntl.h index a53ca808b2..499c67260e 100644 --- a/components/libc/compilers/newlib/sys/fcntl.h +++ b/components/libc/compilers/newlib/sys/fcntl.h @@ -13,6 +13,4 @@ #define O_DIRECTORY 0x0200000 #define O_BINARY 0x0008000 -#include <unistd.h> - #endif diff --git a/components/libc/compilers/newlib/sys/termios.h b/components/libc/compilers/newlib/sys/termios.h new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/components/libc/compilers/newlib/sys/termios.h diff --git a/components/libc/compilers/newlib/syscalls.c b/components/libc/compilers/newlib/syscalls.c index ff09a4fe80..52d2361a04 100644 --- a/components/libc/compilers/newlib/syscalls.c +++ b/components/libc/compilers/newlib/syscalls.c @@ -205,30 +205,23 @@ _wait_r(struct _reent *ptr, int *status) _ssize_t _write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes) { - if (fd < 3) +#ifndef RT_USING_DFS + if (fd == 0) { -#ifdef RT_USING_CONSOLE - rt_device_t console_device; - extern rt_device_t rt_console_get_device(void); + rt_device_t console; - console_device = rt_console_get_device(); - if (console_device != 0) rt_device_write(console_device, 0, buf, nbytes); - return nbytes; -#else - return 0; -#endif + console = rt_console_get_device(); + if (console) return rt_device_write(console, -1, buf, nbytes); } - else - { -#ifdef RT_USING_DFS - _ssize_t rc; - rc = write(fd, buf, nbytes); - return rc; + return 0; + #else - return 0; + _ssize_t rc; + + rc = write(fd, buf, nbytes); + return rc; #endif - } } #endif |
