#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned int ui;
static size_t const buffer_size = 4096U;
static char const *input_end = "q";
static bool usage_check(int ac, char *av[]) {
if (ac < 2) {
fprintf(stderr
, "usage: %s filename\n", av
[0]); return false;
}
return true;
}
static void strtrim(char *s) {
char *s1 = s;
/* 最初と最後に出現する空白文字以外の文字の位置を探して左に詰める */
for (; *s1 != '\0' && (*s1 == '\t' || *s1 == ' '); ++s1) /**/;
for (; s < s2 && (*s2 == '\0' || *s2 == '\t' || *s2 == '\n' || *s2 == ' '); --s2) /**/;
for (; s1 <= s2; ) *s++ = *s1++;
*s = '\0';
return;
}
static char *line_search(char *s, char const *key) {
char *s1 = s;
char *s2;
/* 最初に出現する文字 '=' を境に領域を分割し左右それぞれをトリム */
for (; *s1 != '\0' && *s1 != '='; ++s1) /**/;
*s1 = '\0';
s2 = s1 + 1;
s1 = s;
strtrim(s1);
strtrim(s2);
/* 終端まで含めて全て一致しなければ NULL を返す */
for (; ; ++s1, ++key) {
if (*s1 == *key) {
if (*s1 == '\0' && *key == '\0') break;
continue;
}
return NULL;
}
/* キーに対応する(トリム済みの)データ部分を返す */
return s2;
}
static bool file_search(char const *file, char const *key) {
char buffer[buffer_size];
char *cp;
char *data;
FILE
*fp
= fopen(file
, "r"); if (fp == NULL) {
fprintf(stderr
, "error: can't open file. [%s]\n", file
); return false;
}
/* ファイルから一行ずつ読み込んで行検索 */
for (ui a = 1; ; ++a) {
cp
= fgets(buffer
, buffer_size
, fp
); if (cp == NULL) break;
data = line_search(cp, key);
if (data
!= NULL
) fprintf(stdout
, " line:%u key:%s data:%s\n", a
, key
, data
); }
return true;
}
static bool mainloop(char const *file) {
bool r = false;
char buffer[buffer_size];
char *cp;
/* 標準入力から読み込んで(改行が邪魔なので)トリムし終了文字列じゃなければファイル検索 */
for (; ; ) {
fprintf(stdout
, " input key (quit:%s)> ", input_end
); cp
= fgets(buffer
, buffer_size
, stdin
); if (cp == NULL) break;
strtrim(cp);
if (strcmp(cp
, input_end
) == 0) break; r = file_search(file, cp);
if (! r) return r;
}
return r;
}
int main(int ac, char *av[]) {
bool r;
r = usage_check(ac, av);
if (! r) return EXIT_FAILURE;
r = mainloop(av[1]);
if (! r) return EXIT_FAILURE;
return EXIT_SUCCESS;
}
I2luY2x1ZGUgPHN0ZGJvb2wuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKdHlwZWRlZiB1bnNpZ25lZCBpbnQgdWk7CgpzdGF0aWMgc2l6ZV90IGNvbnN0IGJ1ZmZlcl9zaXplID0gNDA5NlU7CnN0YXRpYyBjaGFyIGNvbnN0ICppbnB1dF9lbmQgPSAicSI7CgpzdGF0aWMgYm9vbCB1c2FnZV9jaGVjayhpbnQgYWMsIGNoYXIgKmF2W10pIHsKCWlmIChhYyA8IDIpIHsKCQlmcHJpbnRmKHN0ZGVyciwgInVzYWdlOiAlcyBmaWxlbmFtZVxuIiwgYXZbMF0pOwoJCXJldHVybiBmYWxzZTsKCX0KCglyZXR1cm4gdHJ1ZTsKfQoKc3RhdGljIHZvaWQgc3RydHJpbShjaGFyICpzKSB7CgljaGFyICpzMSA9IHM7CgljaGFyICpzMiA9IHMgKyBzdHJsZW4ocyk7CgoJLyog5pyA5Yid44Go5pyA5b6M44Gr5Ye654++44GZ44KL56m655m95paH5a2X5Lul5aSW44Gu5paH5a2X44Gu5L2N572u44KS5o6i44GX44Gm5bem44Gr6Kmw44KB44KLICovCglmb3IgKDsgKnMxICE9ICdcMCcgJiYgKCpzMSA9PSAnXHQnIHx8ICpzMSA9PSAnICcpOyArK3MxKSAvKiovOwoJZm9yICg7IHMgPCBzMiAmJiAoKnMyID09ICdcMCcgfHwgKnMyID09ICdcdCcgfHwgKnMyID09ICdcbicgfHwgKnMyID09ICcgJyk7IC0tczIpIC8qKi87Cglmb3IgKDsgczEgPD0gczI7ICkgKnMrKyA9ICpzMSsrOwoJKnMgPSAnXDAnOwoKCXJldHVybjsKfQoKc3RhdGljIGNoYXIgKmxpbmVfc2VhcmNoKGNoYXIgKnMsIGNoYXIgY29uc3QgKmtleSkgewoJY2hhciAqczEgPSBzOwoJY2hhciAqczI7CgoJLyog5pyA5Yid44Gr5Ye654++44GZ44KL5paH5a2XICc9JyDjgpLlooPjgavpoJjln5/jgpLliIblibLjgZflt6blj7PjgZ3jgozjgZ7jgozjgpLjg4jjg6rjg6AgKi8KCWZvciAoOyAqczEgIT0gJ1wwJyAmJiAqczEgIT0gJz0nOyArK3MxKSAvKiovOwoJKnMxID0gJ1wwJzsKCXMyID0gczEgKyAxOwoJczEgPSBzOwoJc3RydHJpbShzMSk7CglzdHJ0cmltKHMyKTsKCgkvKiDntYLnq6/jgb7jgaflkKvjgoHjgablhajjgabkuIDoh7TjgZfjgarjgZHjgozjgbAgTlVMTCDjgpLov5TjgZkgKi8KCWZvciAoOyA7ICsrczEsICsra2V5KSB7CgkJaWYgKCpzMSA9PSAqa2V5KSB7CgkJCWlmICgqczEgPT0gJ1wwJyAmJiAqa2V5ID09ICdcMCcpIGJyZWFrOwoJCQljb250aW51ZTsKCQl9CgkJcmV0dXJuIE5VTEw7Cgl9CgoJLyog44Kt44O844Gr5a++5b+c44GZ44KLKOODiOODquODoOa4iOOBv+OBrinjg4fjg7zjgr/pg6jliIbjgpLov5TjgZkgKi8KCXJldHVybiBzMjsKfQoKc3RhdGljIGJvb2wgZmlsZV9zZWFyY2goY2hhciBjb25zdCAqZmlsZSwgY2hhciBjb25zdCAqa2V5KSB7CgljaGFyIGJ1ZmZlcltidWZmZXJfc2l6ZV07CgljaGFyICpjcDsKCWNoYXIgKmRhdGE7CglGSUxFICpmcCA9IGZvcGVuKGZpbGUsICJyIik7CglpZiAoZnAgPT0gTlVMTCkgewoJCWZwcmludGYoc3RkZXJyLCAiZXJyb3I6IGNhbid0IG9wZW4gZmlsZS4gWyVzXVxuIiwgZmlsZSk7CgkJcmV0dXJuIGZhbHNlOwoJfQoKCS8qIOODleOCoeOCpOODq+OBi+OCieS4gOihjOOBmuOBpOiqreOBv+i+vOOCk+OBp+ihjOaknOe0oiAqLwoJZm9yICh1aSBhID0gMTsgOyArK2EpIHsKCQljcCA9IGZnZXRzKGJ1ZmZlciwgYnVmZmVyX3NpemUsIGZwKTsKCQlpZiAoY3AgPT0gTlVMTCkgYnJlYWs7CgkJZGF0YSA9IGxpbmVfc2VhcmNoKGNwLCBrZXkpOwoJCWlmIChkYXRhICE9IE5VTEwpIGZwcmludGYoc3Rkb3V0LCAiIGxpbmU6JXUga2V5OiVzIGRhdGE6JXNcbiIsIGEsIGtleSwgZGF0YSk7Cgl9CgoJZmNsb3NlKGZwKTsKCglyZXR1cm4gdHJ1ZTsKfQoKc3RhdGljIGJvb2wgbWFpbmxvb3AoY2hhciBjb25zdCAqZmlsZSkgewoJYm9vbCByID0gZmFsc2U7CgljaGFyIGJ1ZmZlcltidWZmZXJfc2l6ZV07CgljaGFyICpjcDsKCgkvKiDmqJnmupblhaXlipvjgYvjgonoqq3jgb/ovrzjgpPjgaco5pS56KGM44GM6YKq6a2U44Gq44Gu44GnKeODiOODquODoOOBl+e1guS6huaWh+Wtl+WIl+OBmOOCg+OBquOBkeOCjOOBsOODleOCoeOCpOODq+aknOe0oiAqLwoJZm9yICg7IDsgKSB7CgkJZnByaW50ZihzdGRvdXQsICIgaW5wdXQga2V5IChxdWl0OiVzKT4gIiwgaW5wdXRfZW5kKTsKCQljcCA9IGZnZXRzKGJ1ZmZlciwgYnVmZmVyX3NpemUsIHN0ZGluKTsKCQlpZiAoY3AgPT0gTlVMTCkgYnJlYWs7CgkJc3RydHJpbShjcCk7CgkJaWYgKHN0cmNtcChjcCwgaW5wdXRfZW5kKSA9PSAwKSBicmVhazsKCQlyID0gZmlsZV9zZWFyY2goZmlsZSwgY3ApOwoJCWlmICghIHIpIHJldHVybiByOwoJfQoKCXJldHVybiByOwp9CgppbnQgbWFpbihpbnQgYWMsIGNoYXIgKmF2W10pIHsKCWJvb2wgcjsKCglyID0gdXNhZ2VfY2hlY2soYWMsIGF2KTsKCWlmICghIHIpIHJldHVybiBFWElUX0ZBSUxVUkU7CgoJciA9IG1haW5sb29wKGF2WzFdKTsKCWlmICghIHIpIHJldHVybiBFWElUX0ZBSUxVUkU7CgoJcmV0dXJuIEVYSVRfU1VDQ0VTUzsKfQo=