3 * @author Shinichiro Nakamura
4 * @brief motファイルモジュールの実装。
8 * ===============================================================
9 * mot file interface library
11 * ===============================================================
12 * Copyright (c) 2010-2011 Shinichiro Nakamura
14 * Permission is hereby granted, free of charge, to any person
15 * obtaining a copy of this software and associated documentation
16 * files (the "Software"), to deal in the Software without
17 * restriction, including without limitation the rights to use,
18 * copy, modify, merge, publish, distribute, sublicense, and/or
19 * sell copies of the Software, and to permit persons to whom the
20 * Software is furnished to do so, subject to the following
23 * The above copyright notice and this permission notice shall be
24 * included in all copies or substantial portions of the Software.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
28 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
30 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
31 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 * ===============================================================
43 * @brief 文字列に含まれる制御コードを取り除く。
45 * この関数は制御コードを見つけるとNULLに置き換える。
46 * 文字列の途中に制御コードが見つかった場合、
47 * それはNULLとなり文字列の終端となる。
48 * 文字列の途中に制御コードが含まれるケースを今回は
51 static void text_trim(char *txt) {
52 const int len = strlen(txt);
53 for (int i = 0; i < len; i++) {
54 if ((txt[i] == '\r') || (txt[i] == '\n') || (txt[i] == '\t')) {
61 * @brief 与えられた文字を16進数として解釈し値を得る。
66 static unsigned int get_hex_num(const char c) {
67 static const char *hextxt = "0123456789ABCDEF";
68 for (int i = 0; i < 16; i++) {
78 * @param p mot構造体。(コールバック関数などの情報を参照する。)
83 static int parse_record(mot_t *p, const char *txt)
85 unsigned char buf[BUFSIZ];
88 * 与えられた文字列は少なくとも4バイト長なければおかしい。
90 const int txtlen = strlen(txt);
105 if (!isdigit(txt[1])) {
110 * その次の2バイトはレコードに含まれるアドレスからチェックサムまでのデータバイト数である。
111 * ここでバイト数とテキスト長を比較して正当なレコードであることを検証する。
113 const int datlen = (get_hex_num(txt[2]) * 0x10) + (get_hex_num(txt[3] * 0x01));
114 if ((datlen * 2) != txtlen - 4) {
120 * チェックサムはデータ長からチェックサムの前までの加算に対して1の補数をとったものである。
122 * 1. チェックサムの計算とデータの格納を行う。
123 * 2. チェックサムの妥当性を検証する。
125 * 同時に内部バッファ(buf)にデータをコピーする。
126 * 内部バッファ(buf)にはデータバイト数以降のデータが格納される。
128 unsigned char chksum = datlen;
129 for (int i = 0; i < datlen; i++) {
130 buf[i] = (get_hex_num(txt[4 + (i * 2)]) * 0x10) + (get_hex_num(txt[5 + (i * 2)] * 0x01));
131 if (i < datlen - 1) {
135 unsigned char verify = ~buf[datlen - 1];
136 if (chksum != verify) {
143 * ここでレコードの種類によって呼び出す関数を分けることもできる。
145 * この関数に渡された元データのゼロから数えて第1バイト目がレコードの種類を示している。
152 // @todo 必要になったら実装する。
156 * データレコード。(16ビットアドレスデータ)
158 if (p->cb_data != NULL) {
160 (buf[0] * 0x00000100) +
161 (buf[1] * 0x00000001);
162 p->cb_data(addr, buf + 2, datlen - 2 - 1);
167 * データレコード。(24ビットアドレスデータ)
169 if (p->cb_data != NULL) {
171 (buf[0] * 0x00010000) +
172 (buf[1] * 0x00000100) +
173 (buf[2] * 0x00000001);
174 p->cb_data(addr, buf + 3, datlen - 3 - 1);
179 * データレコード。(32ビットアドレスデータ)
181 if (p->cb_data != NULL) {
183 (buf[0] * 0x01000000) +
184 (buf[1] * 0x00010000) +
185 (buf[2] * 0x00000100) +
186 (buf[3] * 0x00000001);
187 p->cb_data(addr, buf + 4, datlen - 4 - 1);
194 // @todo 必要になったら実装する。
200 // @todo 必要になったら実装する。
206 // @todo 必要になったら実装する。
210 * データレコード終了。(32ビットアドレスデータ)
212 // @todo 必要になったら実装する。
216 * データレコード終了。(24ビットアドレスデータ)
218 // @todo 必要になったら実装する。
222 * データレコード終了。(16ビットアドレスデータ)
224 // @todo 必要になったら実装する。
237 * @brief motファイルを読み込む。
239 * @param filename ファイル名。(NULLを与えると標準入力を入力とする。)
240 * @param p mot構造体。(コールバック関数などの情報を参照する。)
245 int mot_read(const char *filename, mot_t *p)
250 if (filename == NULL) {
252 * 標準入力を入力用ファイルとして用いる。
262 fp = fopen(filename, "r");
269 * レコードを1つずつ読み込んでパースする。
271 while (fgets(buf, sizeof(buf), fp)) {
272 const int len = strlen(buf);
275 if (parse_record(p, buf) != 0) {