OSDN Git Service

チケット #30493 , チケット #30494 , チケット #30502
[uzume/uzume_bfin.git] / uzumeapp / kernel / uzume / ntshell / ntopt.c
1 /**
2  * @file ntopt.c
3  * @author Shinichiro Nakamura
4  * @brief NT-Shell用オプション解析モジュールの実装。
5  */
6
7 /*
8  * ===============================================================
9  *  Natural Tiny Shell (NT-Shell)
10  * ===============================================================
11  * Copyright (c) 2010-2012 Shinichiro Nakamura
12  *
13  * Permission is hereby granted, free of charge, to any person
14  * obtaining a copy of this software and associated documentation
15  * files (the "Software"), to deal in the Software without
16  * restriction, including without limitation the rights to use,
17  * copy, modify, merge, publish, distribute, sublicense, and/or
18  * sell copies of the Software, and to permit persons to whom the
19  * Software is furnished to do so, subject to the following
20  * conditions:
21  *
22  * The above copyright notice and this permission notice shall be
23  * included in all copies or substantial portions of the Software.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
27  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
29  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
30  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
31  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
32  * OTHER DEALINGS IN THE SOFTWARE.
33  * ===============================================================
34  */
35
36 #include "ntopt.h"
37
38 /**
39  * @brief 与えられた文字がデリミタであるかどうかを判定する。
40  * @param c 文字。
41  * @retval true デリミタである。
42  * @retval false デリミタでない。
43  */
44 #define IS_DELIM(c) \
45     (((c) == '\r') || ((c) == '\n') || ((c) == '\t') || ((c) == '\0') || ((c) == ' '))
46
47 static int ntopt_get_count(const char *str);
48 static char *ntopt_get_text(
49         const char *str, const int n, char *buf, int siz, int *len);
50
51 /**
52  * @brief 与えられた文字列のセンテンス数を取得する。
53  * @param str 文字列。
54  * @return センテンス数。
55  */
56 static int ntopt_get_count(const char *str)
57 {
58     int cnt = 0;
59     int wc = 0;
60     char *p = (char *)str;
61     while (*p) {
62         if (!IS_DELIM(*p)) {
63             wc++;
64             if (wc == 1) {
65                 cnt++;
66             }
67         } else {
68             wc = 0;
69         }
70         p++;
71     }
72     return cnt;
73 }
74
75 /**
76  * @brief 与えられた文字列のセンテンスを取得する。
77  * @param str 文字列。
78  * @param n センテンス。(0からntopt-get_count(str) - 1までの値。)
79  * @param buf 格納バッファ。
80  * @param siz 格納バッファのサイズ。
81  * @param len 格納した文字列のサイズ。
82  * @retval !NULL 取得成功。格納バッファへのポインタ。
83  * @retval NULL 取得失敗。
84  */
85 static char *ntopt_get_text(
86         const char *str, const int n, char *buf, int siz, int *len)
87 {
88     int cnt = 0;
89     int wc = 0;
90     char *p = (char *)str;
91     *len = 0;
92     while (*p) {
93         if (!IS_DELIM(*p)) {
94             wc++;
95             if ((wc == 1)) {
96                 if (cnt == n) {
97                     char *des = buf;
98                     int cc = 0;
99                     while (!IS_DELIM(*p)) {
100                         cc++;
101                         if (siz <= cc) {
102                             break;
103                         }
104                         *des = *p;
105                         des++;
106                         p++;
107                     }
108                     *des = '\0';
109                     *len = cc;
110                     return buf;
111                 }
112                 cnt++;
113             }
114         } else {
115             wc = 0;
116         }
117         p++;
118     }
119     return '\0';
120 }
121
122 /**
123  * @brief 与えられた文字列をデリミタで分割する。
124  * @param str 文字列。
125  * @param func コールバック関数。
126  * @param extobj 拡張オブジェクト。
127  * @return コールバック関数が返した値。
128  */
129 int ntopt_parse(const char *str, NTOPT_CALLBACK func, void *extobj)
130 {
131     int argc;
132     char argv[NTOPT_TEXT_MAXLEN];
133     char *argvp[NTOPT_TEXT_MAXARGS];
134     int i;
135     int total;
136     char *p;
137
138     argc = ntopt_get_count(str);
139     if (NTOPT_TEXT_MAXARGS <= argc) {
140         argc = NTOPT_TEXT_MAXARGS;
141     }
142
143     total = 0;
144     p = &argv[0];
145     for (i = 0; i < argc; i++) {
146         int len;
147         argvp[i] = ntopt_get_text(
148                 str, i, p, NTOPT_TEXT_MAXLEN - total, &len);
149         if (total + len + 1 < NTOPT_TEXT_MAXLEN) {
150             p += len + 1;
151             total += len + 1;
152         } else {
153             break;
154         }
155     }
156
157     return func(argc, &argvp[0], extobj);
158 }
159