source: asp3_tinet_ecnl_rx/trunk/ntshell/ntshell/util/ntstdio.c@ 387

Last change on this file since 387 was 387, checked in by coas-nagasima, 5 years ago

ファイルディスクリプタ処理を更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 9.3 KB
Line 
1/**
2 * @file ntstdio.c
3 * @author CuBeatSystems
4 * @author Shinichiro Nakamura
5 * @copyright
6 * ===============================================================
7 * Natural Tiny Shell (NT-Shell) Version 0.3.1
8 * ===============================================================
9 * Copyright (c) 2010-2016 Shinichiro Nakamura
10 *
11 * Permission is hereby granted, free of charge, to any person
12 * obtaining a copy of this software and associated documentation
13 * files (the "Software"), to deal in the Software without
14 * restriction, including without limitation the rights to use,
15 * copy, modify, merge, publish, distribute, sublicense, and/or
16 * sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following
18 * conditions:
19 *
20 * The above copyright notice and this permission notice shall be
21 * included in all copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
25 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30 * OTHER DEALINGS IN THE SOFTWARE.
31 */
32
33/*------------------------------------------------------------------------/
34/ Universal string handler for user console interface
35/-------------------------------------------------------------------------/
36/
37/ Copyright (C) 2011, ChaN, all right reserved.
38/
39/ * This software is a free software and there is NO WARRANTY.
40/ * No restriction on use. You can use, modify and redistribute it for
41/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
42/ * Redistributions of source code must retain the above copyright notice.
43/
44/-------------------------------------------------------------------------*/
45
46#include <stdarg.h>
47#include "ntstdio.h"
48
49#define FLAG_ZERO_PADDED (1 << 0)
50#define FLAG_LEFT_JUSTIFIED (1 << 1)
51#define FLAG_SIZE_LONG_INT (1 << 2)
52#define FLAG_SIGNED_DECIMAL (1 << 3)
53#define FLAG_SIZE_HALF_INT (1 << 4)
54
55/*
56 * ntstdio_printf("%d", 1234); "1234"
57 * ntstdio_printf("%6d,%3d%%", -200, 5); " -200, 5%"
58 * ntstdio_printf("%-6u", 100); "100 "
59 * ntstdio_printf("%ld", 12345678L); "12345678"
60 * ntstdio_printf("%04x", 0xA3); "00a3"
61 * ntstdio_printf("%08LX", 0x123ABC); "00123ABC"
62 * ntstdio_printf("%016b", 0x550F); "0101010100001111"
63 * ntstdio_printf("%s", "String"); "String"
64 * ntstdio_printf("%-4s", "abc"); "abc "
65 * ntstdio_printf("%4s", "abc"); " abc"
66 * ntstdio_printf("%c", 'a'); "a"
67 * ntstdio_printf("%f", 10.0); <ntstdio_printf lacks floating point support>
68 */
69
70static int xvprintf(ntstdio_t *handle, const char *fmt, va_list arp)
71{
72 unsigned int i, j;
73 unsigned int flag, radix, width;
74 unsigned long value;
75 char s[16], c, d, *p;
76
77 while (1) {
78 /*
79 * Get a character.
80 */
81 c = *fmt++;
82 if (!c) {
83 /*
84 * End of the format.
85 */
86 break;
87 }
88 if (c != '%') {
89 /*
90 * Pass through it if not a % sequense
91 */
92 ntstdio_putc(handle, c);
93 continue;
94 }
95
96 /*
97 * Reset the flag.
98 */
99 flag = 0;
100
101 /*
102 * Get the first character of the sequense.
103 */
104 c = *fmt++;
105 if (c == '0') {
106 flag = FLAG_ZERO_PADDED;
107 c = *fmt++;
108 }
109 else {
110 if (c == '-') {
111 flag = FLAG_LEFT_JUSTIFIED;
112 c = *fmt++;
113 }
114 }
115 /*
116 * Calculate the minimum width.
117 */
118 for (width = 0; (c >= '0') && (c <= '9'); c = *fmt++) {
119 width = (width * 10) + (c - '0');
120 }
121 if ((c == 'l') || (c == 'L')) {
122 flag |= FLAG_SIZE_LONG_INT;
123 c = *fmt++;
124 }
125 else if (c == 'h') { /* Prefix: Size is short int */
126 flag |= FLAG_SIZE_HALF_INT;
127 c = *fmt++;
128 }
129 if (!c) {
130 /*
131 * End of the format.
132 */
133 break;
134 }
135 d = c;
136 if (d >= 'a') {
137 d -= 0x20;
138 }
139 /* Type is... */
140 switch (d) {
141 case 'S':
142 /* String */
143 p = va_arg(arp, char*);
144 for (j = 0; p[j]; j++) {
145 }
146 while (!(flag & FLAG_LEFT_JUSTIFIED) && (j++ < width)) {
147 ntstdio_putc(handle, ' ');
148 }
149 ntstdio_puts(handle, p);
150 while (j++ < width) {
151 ntstdio_putc(handle, ' ');
152 }
153 continue;
154 case 'C':
155 /* Character */
156 ntstdio_putc(handle, (char)va_arg(arp, int));
157 continue;
158 case 'B':
159 /* Binary */
160 radix = 2;
161 break;
162 case 'O':
163 /* Octal */
164 radix = 8;
165 break;
166 case 'D':
167 /* Signed decimal */
168 radix = 10;
169 break;
170 case 'U':
171 /* Unsigned decimal */
172 radix = 10;
173 break;
174 case 'X':
175 /* Hexdecimal */
176 radix = 16;
177 break;
178 default:
179 /* Unknown type (passthrough) */
180 ntstdio_putc(handle, c);
181 continue;
182 }
183
184 /*
185 * Get an argument and put it in numeral.
186 */
187 value = (flag & FLAG_SIZE_LONG_INT) ? va_arg(arp, long)
188 : (flag & FLAG_SIZE_HALF_INT) ? ((d == 'D') ? (long)((short)va_arg(arp, int)) : (long)((unsigned short)va_arg(arp, unsigned int)))
189 : ((d == 'D') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int));
190 if ((d == 'D') && (value & 0x80000000)) {
191 value = 0 - value;
192 flag |= FLAG_SIGNED_DECIMAL;
193 }
194 i = 0;
195 do {
196 d = (char)(value % radix);
197 value /= radix;
198 if (d > 9) {
199 d += (c == 'x') ? 0x27 : 0x07;
200 }
201 s[i++] = d + '0';
202 } while (value && (i < sizeof(s)));
203 if (flag & FLAG_SIGNED_DECIMAL) {
204 s[i++] = '-';
205 }
206 j = i;
207 d = (flag & FLAG_ZERO_PADDED) ? '0' : ' ';
208 while (!(flag & FLAG_LEFT_JUSTIFIED) && (j++ < width)) {
209 ntstdio_putc(handle, d);
210 }
211 do {
212 ntstdio_putc(handle, s[--i]);
213 } while (i);
214 while (j++ < width) {
215 ntstdio_putc(handle, ' ');
216 }
217 }
218
219 return handle->pos;
220}
221
222void ntstdio_init(ntstdio_t *handle, unsigned int option, NTSTDIO_XI xi, NTSTDIO_XO xo)
223{
224 handle->xi = xi;
225 handle->xo = xo;
226 handle->pos = 0;
227 handle->option = option;
228}
229
230static void _putc(ntstdio_t *handle, char c)
231{
232 if (handle->xo) {
233 handle->xo(handle, (unsigned char)c);
234 }
235 handle->pos++;
236}
237
238void ntstdio_putc(ntstdio_t *handle, char c)
239{
240 if ((handle->option & NTSTDIO_OPTION_LF_CRLF) && (c == '\n')) {
241 _putc(handle, '\r');
242 _putc(handle, '\n');
243 }
244 else{
245 _putc(handle, c);
246 }
247}
248
249void ntstdio_puts(ntstdio_t *handle, const char *str)
250{
251 while (*str) {
252 ntstdio_putc(handle, *str++);
253 }
254}
255
256void ntstdio_fputs(ntstdio_t *handle, NTSTDIO_XO xo, const char *str)
257{
258 NTSTDIO_XO pf;
259
260 /* Save current output device */
261 pf = handle->xo;
262 /* Switch output to specified device */
263 handle->xo = xo;
264
265 while (*str) {
266 ntstdio_putc(handle, *str++);
267 }
268
269 /* Restore output device */
270 handle->xo = pf;
271}
272
273int ntstdio_printf(ntstdio_t *handle, const char *fmt, ...)
274{
275 int result;
276 va_list arp;
277 va_start(arp, fmt);
278 result = xvprintf(handle, fmt, arp);
279 va_end(arp);
280 return result;
281}
282
283struct put_buf_t {
284 char *outptr;
285 int len;
286};
287
288static void put_buf(struct ntstdio_t *handle, unsigned char c)
289{
290 struct put_buf_t *put_buf = (struct put_buf_t *)handle->exinf;
291 if ((handle->pos + 1) >= put_buf->len)
292 return;
293 put_buf->outptr[handle->pos] = (char)c;
294 handle->pos++;
295}
296
297int ntstdio_snprintf(char *buf, int len, const char *fmt, ...)
298{
299 int result;
300 ntstdio_t handle;
301 struct put_buf_t exinf;
302 va_list arp;
303 /* Switch destination for memory */
304 handle.xo = put_buf;
305 handle.option = 0;
306 handle.pos = 0;
307 handle.exinf = &exinf;
308 exinf.outptr = buf;
309 exinf.len = len;
310
311 va_start(arp, fmt);
312 result = xvprintf(&handle, fmt, arp);
313 va_end(arp);
314
315 /* Terminate output string with a \0 */
316 buf[handle.pos] = '\0';
317 return result;
318}
319
320int ntstdio_fprintf(ntstdio_t *handle, NTSTDIO_XO xo, const char *fmt, ...)
321{
322 int result;
323 va_list arp;
324 NTSTDIO_XO pf;
325
326 /* Save current output device */
327 pf = handle->xo;
328 /* Switch output to specified device */
329 handle->xo = xo;
330
331 va_start(arp, fmt);
332 result = xvprintf(handle, fmt, arp);
333 va_end(arp);
334
335 /* Restore output device */
336 handle->xo = pf;
337 return result;
338}
339
340int ntstdio_getc(ntstdio_t *handle)
341{
342 extern void shell_exit(int cd);
343
344 int c = handle->xi(handle);
345 if (handle->option & NTSTDIO_OPTION_LF_CR) {
346 if (c == '\r')
347 c = '\n';
348 }
349 if (handle->option & NTSTDIO_OPTION_CANON) {
350 if (c == 0x03)
351 shell_exit(-1);
352 }
353 if (handle->option & NTSTDIO_OPTION_LINE_ECHO) {
354 ntstdio_putc(handle, c);
355 }
356 return c;
357}
358
359/* 0:End of stream, 1:A line arrived */
360int ntstdio_gets(ntstdio_t *handle, char *buf, int len)
361{
362 int c, i;
363
364 if (!handle->xi) {
365 /* No input function specified */
366 return 0;
367 }
368
369 i = 0;
370 for (;;) {
371 /* Get a char from the incoming stream */
372 c = handle->xi(handle);
373 if (!c) {
374 /* End of stream */
375 return 0;
376 }
377 if (c == '\r') {
378 /* End of line */
379 break;
380 }
381 if ((c == '\b') && i) {
382 /* Back space */
383 i--;
384 if (handle->option & NTSTDIO_OPTION_LINE_ECHO) {
385 ntstdio_putc(handle, c);
386 }
387 continue;
388 }
389 if ((c >= ' ') && (i < len - 1)) {
390 /* Visible chars */
391 buf[i++] = c;
392 if (handle->option & NTSTDIO_OPTION_LINE_ECHO) {
393 ntstdio_putc(handle, c);
394 }
395 }
396 }
397 buf[i] = 0;
398 /* Terminate with a \0 */
399 if (handle->option & NTSTDIO_OPTION_LINE_ECHO) {
400 ntstdio_putc(handle, '\n');
401 }
402 return 1;
403}
404
405/* 0:End of stream, 1:A line arrived */
406int ntstdio_fgets(ntstdio_t *handle, NTSTDIO_XI xi, char *buf, int len)
407{
408 NTSTDIO_XI pf;
409 int n;
410
411 /* Save current input device */
412 pf = handle->xi;
413 /* Switch input to specified device */
414 handle->xi = xi;
415 /* Get a line */
416 n = ntstdio_gets(handle, buf, len);
417 /* Restore input device */
418 handle->xi = pf;
419
420 return n;
421}
Note: See TracBrowser for help on using the repository browser.