Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-src by
stdio.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "platform.h" 00017 #include "FileHandle.h" 00018 #include "FileSystemLike.h" 00019 #include "FilePath.h" 00020 #include "serial_api.h" 00021 #include <errno.h> 00022 00023 #if defined(__ARMCC_VERSION) 00024 # include <rt_sys.h> 00025 # define PREFIX(x) _sys##x 00026 # define OPEN_MAX _SYS_OPEN 00027 # ifdef __MICROLIB 00028 # pragma import(__use_full_stdio) 00029 # endif 00030 00031 #elif defined(__ICCARM__) 00032 # include <yfuns.h> 00033 # define PREFIX(x) _##x 00034 # define OPEN_MAX 16 00035 00036 # define STDIN_FILENO 0 00037 # define STDOUT_FILENO 1 00038 # define STDERR_FILENO 2 00039 00040 #else 00041 # include <sys/stat.h> 00042 # include <sys/unistd.h> 00043 # include <sys/syslimits.h> 00044 # define PREFIX(x) x 00045 #endif 00046 00047 using namespace mbed; 00048 00049 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00050 // Before version 5.03, we were using a patched version of microlib with proper names 00051 extern const char __stdin_name[] = ":tt"; 00052 extern const char __stdout_name[] = ":tt"; 00053 extern const char __stderr_name[] = ":tt"; 00054 00055 #else 00056 extern const char __stdin_name[] = "/stdin"; 00057 extern const char __stdout_name[] = "/stdout"; 00058 extern const char __stderr_name[] = "/stderr"; 00059 #endif 00060 00061 /* newlib has the filehandle field in the FILE struct as a short, so 00062 * we can't just return a Filehandle* from _open and instead have to 00063 * put it in a filehandles array and return the index into that array 00064 * (or rather index+3, as filehandles 0-2 are stdin/out/err). 00065 */ 00066 static FileHandle *filehandles[OPEN_MAX]; 00067 00068 FileHandle::~FileHandle() { 00069 /* Remove all open filehandles for this */ 00070 for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00071 if (filehandles[fh_i] == this) { 00072 filehandles[fh_i] = NULL; 00073 } 00074 } 00075 } 00076 00077 #if DEVICE_SERIAL 00078 extern int stdio_uart_inited; 00079 extern serial_t stdio_uart; 00080 #endif 00081 00082 static void init_serial() { 00083 #if DEVICE_SERIAL 00084 if (stdio_uart_inited) return; 00085 serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX); 00086 #endif 00087 } 00088 00089 static inline int openmode_to_posix(int openmode) { 00090 int posix = openmode; 00091 #ifdef __ARMCC_VERSION 00092 if (openmode & OPEN_PLUS) { 00093 posix = O_RDWR; 00094 } else if(openmode & OPEN_W) { 00095 posix = O_WRONLY; 00096 } else if(openmode & OPEN_A) { 00097 posix = O_WRONLY|O_APPEND; 00098 } else { 00099 posix = O_RDONLY; 00100 } 00101 /* a, w, a+, w+ all create if file does not already exist */ 00102 if (openmode & (OPEN_A|OPEN_W)) { 00103 posix |= O_CREAT; 00104 } 00105 /* w and w+ truncate */ 00106 if (openmode & OPEN_W) { 00107 posix |= O_TRUNC; 00108 } 00109 #elif defined(__ICCARM__) 00110 switch (openmode & _LLIO_RDWRMASK) { 00111 case _LLIO_RDONLY: posix = O_RDONLY; break; 00112 case _LLIO_WRONLY: posix = O_WRONLY; break; 00113 case _LLIO_RDWR : posix = O_RDWR ; break; 00114 } 00115 if (openmode & _LLIO_CREAT ) posix |= O_CREAT; 00116 if (openmode & _LLIO_APPEND) posix |= O_APPEND; 00117 if (openmode & _LLIO_TRUNC ) posix |= O_TRUNC; 00118 #endif 00119 return posix; 00120 } 00121 00122 extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) { 00123 /* Use the posix convention that stdin,out,err are filehandles 0,1,2. 00124 */ 00125 if (std::strcmp(name, __stdin_name) == 0) { 00126 init_serial(); 00127 return 0; 00128 } else if (std::strcmp(name, __stdout_name) == 0) { 00129 init_serial(); 00130 return 1; 00131 } else if (std::strcmp(name, __stderr_name) == 0) { 00132 init_serial(); 00133 return 2; 00134 } 00135 00136 // find the first empty slot in filehandles 00137 unsigned int fh_i; 00138 for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00139 if (filehandles[fh_i] == NULL) break; 00140 } 00141 if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) { 00142 return -1; 00143 } 00144 00145 FileHandle *res; 00146 00147 /* FILENAME: ":0x12345678" describes a FileLike* */ 00148 if (name[0] == ':') { 00149 void *p; 00150 sscanf(name, ":%p", &p); 00151 res = (FileHandle*)p; 00152 00153 /* FILENAME: "/file_system/file_name" */ 00154 } else { 00155 FilePath path(name); 00156 00157 if (path.isFile()) { 00158 res = path.file(); 00159 } else { 00160 FileSystemLike *fs = path.fileSystem(); 00161 if (fs == NULL) return -1; 00162 int posix_mode = openmode_to_posix(openmode); 00163 res = fs->open(path.fileName(), posix_mode); /* NULL if fails */ 00164 } 00165 } 00166 00167 if (res == NULL) return -1; 00168 filehandles[fh_i] = res; 00169 00170 return fh_i + 3; // +3 as filehandles 0-2 are stdin/out/err 00171 } 00172 00173 extern "C" int PREFIX(_close)(FILEHANDLE fh) { 00174 if (fh < 3) return 0; 00175 00176 FileHandle* fhc = filehandles[fh-3]; 00177 filehandles[fh-3] = NULL; 00178 if (fhc == NULL) return -1; 00179 00180 return fhc->close(); 00181 } 00182 00183 #if defined(__ICCARM__) 00184 extern "C" size_t __write (int fh, const unsigned char *buffer, size_t length) { 00185 #else 00186 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) { 00187 #endif 00188 int n; // n is the number of bytes written 00189 if (fh < 3) { 00190 #if DEVICE_SERIAL 00191 if (!stdio_uart_inited) init_serial(); 00192 for (unsigned int i = 0; i < length; i++) { 00193 serial_putc(&stdio_uart, buffer[i]); 00194 } 00195 #endif 00196 n = length; 00197 } else { 00198 FileHandle* fhc = filehandles[fh-3]; 00199 if (fhc == NULL) return -1; 00200 00201 n = fhc->write(buffer, length); 00202 } 00203 #ifdef __ARMCC_VERSION 00204 return length-n; 00205 #else 00206 return n; 00207 #endif 00208 } 00209 00210 #if defined(__ICCARM__) 00211 extern "C" size_t __read (int fh, unsigned char *buffer, size_t length) { 00212 #else 00213 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) { 00214 #endif 00215 int n; // n is the number of bytes read 00216 if (fh < 3) { 00217 // only read a character at a time from stdin 00218 #if DEVICE_SERIAL 00219 *buffer = serial_getc(&stdio_uart); 00220 #endif 00221 n = 1; 00222 } else { 00223 FileHandle* fhc = filehandles[fh-3]; 00224 if (fhc == NULL) return -1; 00225 00226 n = fhc->read(buffer, length); 00227 } 00228 #ifdef __ARMCC_VERSION 00229 return length-n; 00230 #else 00231 return n; 00232 #endif 00233 } 00234 00235 #ifdef __ARMCC_VERSION 00236 extern "C" int PREFIX(_istty)(FILEHANDLE fh) 00237 #else 00238 extern "C" int _isatty(FILEHANDLE fh) 00239 #endif 00240 { 00241 /* stdin, stdout and stderr should be tty */ 00242 if (fh < 3) return 1; 00243 00244 FileHandle* fhc = filehandles[fh-3]; 00245 if (fhc == NULL) return -1; 00246 00247 return fhc->isatty(); 00248 } 00249 00250 extern "C" 00251 #if defined(__ARMCC_VERSION) 00252 int _sys_seek(FILEHANDLE fh, long position) 00253 #elif defined(__ICCARM__) 00254 long __lseek(int fh, long offset, int whence) 00255 #else 00256 int _lseek(FILEHANDLE fh, int offset, int whence) 00257 #endif 00258 { 00259 if (fh < 3) return 0; 00260 00261 FileHandle* fhc = filehandles[fh-3]; 00262 if (fhc == NULL) return -1; 00263 00264 #if defined(__ARMCC_VERSION) 00265 return fhc->lseek(position, SEEK_SET); 00266 #else 00267 return fhc->lseek(offset, whence); 00268 #endif 00269 } 00270 00271 #ifdef __ARMCC_VERSION 00272 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) { 00273 if (fh < 3) return 0; 00274 00275 FileHandle* fhc = filehandles[fh-3]; 00276 if (fhc == NULL) return -1; 00277 00278 return fhc->fsync(); 00279 } 00280 00281 extern "C" long PREFIX(_flen)(FILEHANDLE fh) { 00282 if (fh < 3) return 0; 00283 00284 FileHandle* fhc = filehandles[fh-3]; 00285 if (fhc == NULL) return -1; 00286 00287 return fhc->flen(); 00288 } 00289 #endif 00290 00291 00292 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__) 00293 extern "C" int _fstat(int fd, struct stat *st) { 00294 if ((STDOUT_FILENO == fd) || (STDERR_FILENO == fd) || (STDIN_FILENO == fd)) { 00295 st->st_mode = S_IFCHR; 00296 return 0; 00297 } 00298 00299 errno = EBADF; 00300 return -1; 00301 } 00302 #endif 00303 00304 namespace std { 00305 extern "C" int remove(const char *path) { 00306 FilePath fp(path); 00307 FileSystemLike *fs = fp.fileSystem(); 00308 if (fs == NULL) return -1; 00309 00310 return fs->remove(fp.fileName()); 00311 } 00312 00313 extern "C" int rename(const char *oldname, const char *newname) { 00314 return -1; 00315 } 00316 00317 extern "C" char *tmpnam(char *s) { 00318 return NULL; 00319 } 00320 00321 extern "C" FILE *tmpfile() { 00322 return NULL; 00323 } 00324 } // namespace std 00325 00326 #ifdef __ARMCC_VERSION 00327 extern "C" char *_sys_command_string(char *cmd, int len) { 00328 return NULL; 00329 } 00330 #endif 00331 00332 extern "C" DIR *opendir(const char *path) { 00333 /* root dir is FileSystemLike */ 00334 if (path[0] == '/' && path[1] == 0) { 00335 return FileSystemLike::opendir(); 00336 } 00337 00338 FilePath fp(path); 00339 FileSystemLike* fs = fp.fileSystem(); 00340 if (fs == NULL) return NULL; 00341 00342 return fs->opendir(fp.fileName()); 00343 } 00344 00345 extern "C" struct dirent *readdir(DIR *dir) { 00346 return dir->readdir(); 00347 } 00348 00349 extern "C" int closedir(DIR *dir) { 00350 return dir->closedir(); 00351 } 00352 00353 extern "C" void rewinddir(DIR *dir) { 00354 dir->rewinddir(); 00355 } 00356 00357 extern "C" off_t telldir(DIR *dir) { 00358 return dir->telldir(); 00359 } 00360 00361 extern "C" void seekdir(DIR *dir, off_t off) { 00362 dir->seekdir(off); 00363 } 00364 00365 extern "C" int mkdir(const char *path, mode_t mode) { 00366 FilePath fp(path); 00367 FileSystemLike *fs = fp.fileSystem(); 00368 if (fs == NULL) return -1; 00369 00370 return fs->mkdir(fp.fileName(), mode); 00371 } 00372 00373 #if defined(TOOLCHAIN_GCC_CR) || defined(TOOLCHAIN_GCC_CS) || defined(TOOLCHAIN_GCC_ARM) 00374 /* prevents the exception handling name demangling code getting pulled in */ 00375 #include "error.h" 00376 namespace __gnu_cxx { 00377 void __verbose_terminate_handler() { 00378 error("Exception"); 00379 } 00380 } 00381 #endif
Generated on Tue Jul 12 2022 13:47:02 by
1.7.2
