diff --git a/src/cmd2F.c b/src/cmd2F.c index aad685e..6468650 100644 --- a/src/cmd2F.c +++ b/src/cmd2F.c @@ -749,14 +749,12 @@ void commands2F44() { char s[256]; if (fig) { - char *ss="%%%dd"; - char sss[256]; - sprintf(sss, ss, fig); - sprintf(s, sss, num2); + sprintf(s, "%*d", fig, num2); + v_strcpy(num1 - 1, s + strlen(s) - fig); } else { sprintf(s, "%d", num2); + v_strcpy(num1 - 1, s); } - v_strcpy(num1 - 1, s); DEBUG_COMMAND("MHH %d, %d, %d:\n", num1, fig, num2); } diff --git a/src/cmdm.c b/src/cmdm.c index be9727d..2a75910 100644 --- a/src/cmdm.c +++ b/src/cmdm.c @@ -135,8 +135,14 @@ void commandMA() { /* num1 の文字列の後ろに num2 をつなげる */ int num1 = getCaliValue(); int num2 = getCaliValue(); - - v_strcat(num1 - 1, v_str(num2 - 1)); + + if (num1 == num2) { + char *buf = strdup(v_str(num2 - 1)); + v_strcat(num1 - 1, buf); + free(buf); + } else { + v_strcat(num1 - 1, v_str(num2 - 1)); + } DEBUG_COMMAND("MA %d,%d:\n",num1,num2); } @@ -176,7 +182,8 @@ void commandMM() { int num1 = getCaliValue(); int num2 = getCaliValue(); - v_strcpy(num1 - 1, v_str(num2 - 1)); + if (num1 != num2) + v_strcpy(num1 - 1, v_str(num2 - 1)); DEBUG_COMMAND("MM %d,%d:\n",num1, num2); } @@ -236,8 +243,7 @@ void commandMD() { int src_str_no = getCaliValue(); int len = getCaliValue(); - strncpy(v_str(dst_str_no - 1), v_str(src_str_no - 1), len * 2); - *(v_str(dst_str_no - 1) + len*2) = '\0'; + v_strncpy(dst_str_no - 1, 0, src_str_no - 1, 0, len); DEBUG_COMMAND("MD %d,%d,%d:\n",dst_str_no, src_str_no, len); } @@ -250,8 +256,7 @@ void commandME() { int src_pos = getCaliValue(); int len = getCaliValue(); - strncpy(v_str(dst_str_no - 1) + dst_pos * 2, v_str(src_str_no - 1) + src_pos * 2, len*2); - *(v_str(dst_str_no - 1) + dst_pos * 2 + len*2) = '\0'; + v_strncpy(dst_str_no - 1, dst_pos, src_str_no - 1, src_pos, len); DEBUG_COMMAND("ME %d,%d,%d,%d,%d:\n",dst_str_no, dst_pos, src_str_no, src_pos, len); } @@ -262,14 +267,13 @@ void commandMF() { int dst_no = getCaliValue(); int key_no = getCaliValue(); int start_pos = getCaliValue(); - char *start = v_str(dst_no - 1) + start_pos * 2; - char *pos = strstr(start, v_str(key_no - 1)); + int pos = v_strstr(dst_no - 1, start_pos, v_str(key_no - 1)); - if (pos == NULL) { + if (pos < 0) { sysVar[0] = 255; } else { - *var = (pos - start) / 2; + *var = pos; sysVar[0] = 0; } @@ -376,26 +380,16 @@ void commandMN() { int num = getCaliValue(); int *var = getCaliVariable(); int i, len; - char *b; + const char *b; switch(no) { case 0: /* 文字列を配列に変換する */ - len = v_strlen(num -1); - b = v_str(num -1); - for (i = 0; i < len; i++) { - *var = *b; - var++; b++; - } - *var = 0; + sysVar[0] = v_strToVars(num - 1, var); break; case 1: /* 配列を文字列に変換する */ - b = v_str(num -1); - while(*var) { - *b = *var; b++; var++; - } - *b = '\0'; + v_strFromVars(num - 1, var); break; default: WARNING("UnKnown MN command(%d)\n", no); diff --git a/src/savedata.c b/src/savedata.c index e3f88e9..351e497 100644 --- a/src/savedata.c +++ b/src/savedata.c @@ -185,7 +185,8 @@ int save_save_str_with_file(char *filename, int start, int cnt) { *tmp = 0; for (i = 0; i < cnt; i++) { strncpy(tmp, v_str(start + i - 1), strvar_len - 1); - tmp += v_strlen(start + i - 1) + 1; + tmp[strvar_len - 1] = '\0'; + tmp += strlen(tmp) + 1; } @@ -241,8 +242,8 @@ int save_load_str_with_file(char *filename, int start, int cnt) { status = SAVE_LOADOK; } for (i = 0; i < cnt; i++) { - strncpy(v_str(start + i - 1), tmp, strvar_len); - tmp += v_strlen(start + i - 1) + 1; + v_strcpy(start + i - 1, tmp); + tmp += strlen(tmp) + 1; } fclose(fp); free(_tmp); @@ -599,7 +600,8 @@ static void *saveStrVar(Ald_strVarHdr *head) { *tmp = 0; for (i = 0; i < strvar_cnt; i++) { strncpy(tmp, v_str(i), strvar_len - 1); - tmp += v_strlen(i) + 1; + tmp[strvar_len - 1] = '\0'; + tmp += strlen(tmp) + 1; } head->size = tmp - _tmp; head->count = strvar_cnt; @@ -618,8 +620,8 @@ static void loadStrVar(char *buf) { v_initStringVars(cnt, max); buf += sizeof(Ald_strVarHdr); for (i = 0; i < cnt; i++) { - strncpy(v_str(i), buf, max - 1); - buf += v_strlen(i) + 1; + v_strcpy(i, buf); + buf += strlen(buf) + 1; } } diff --git a/src/variable.c b/src/variable.c index 107a37d..63cee89 100644 --- a/src/variable.c +++ b/src/variable.c @@ -25,6 +25,7 @@ #include #include #include "portab.h" +#include "utfsjis.h" #include "variable.h" #include "xsystem35.h" @@ -37,11 +38,18 @@ arrayVarBufferStruct arrayVarBuffer[ARRAYVAR_PAGEMAX]; /* 64bit変数 */ double longVar[SYSVARLONG_MAX]; /* 文字列変数 */ -static char *strVar; +static char **strVar; /* 文字列変数の属性(最大,1つあたりの大きさ) */ int strvar_cnt = STRVAR_MAX; int strvar_len = STRVAR_LEN; +static char *advance(const char *s, int n) { + while (*s && n > 0) { + s += CHECKSJIS1BYTE(*s) ? 2 : 1; + n--; + } + return (char *)s; +} /* 配列バッファの確保 DC ,page = 1~ */ extern boolean v_allocateArrayBuffer(int page, int size, boolean flg) { @@ -96,43 +104,164 @@ extern boolean v_getArrayBufferStatus(int page) { /* 文字列変数の再初期化 */ extern void v_initStringVars(int cnt,int len) { - strVar = realloc(strVar, cnt * len); + for (int i = cnt + 1; i < strvar_cnt; i++) { + if (strVar[i]) + free(strVar[i]); + } + strVar = realloc(strVar, cnt * sizeof(char *)); if (strVar == NULL) { NOMEMERR(); } + for (int i = strvar_cnt + 1; i < cnt; i++) + strVar[i] = NULL; strvar_cnt = cnt; strvar_len = len; } /* 変数の初期化 */ extern boolean v_initVars() { - strVar = calloc(STRVAR_MAX, STRVAR_LEN); - + strVar = calloc(STRVAR_MAX, sizeof(char *)); if (strVar == NULL) { NOMEMERR(); } - return true; } /* 文字変数への代入 */ -char *v_strcpy(int no, const char *str) { - return strncpy(strVar + no * strvar_len, str, strvar_len - 1); +void v_strcpy(int no, const char *str) { + if (no < 0 || no >= strvar_cnt) { + WARNING("string index out of range: %d", no); + return; + } + if (strVar[no]) + free(strVar[no]); + strVar[no] = strdup(str); +} + +void v_strncpy(int dstno, int dstpos, int srcno, int srcpos, int len) { + if (dstno < 0 || dstno >= strvar_cnt) { + WARNING("string index out of range: %d", dstno); + return; + } + if (!strVar[dstno]) + strVar[dstno] = strdup(""); + + char *buf = NULL; + const char *src; + if (srcno == dstno) + src = buf = strdup(strVar[srcno]); + else + src = v_str(srcno); + + dstpos = advance(strVar[dstno], dstpos) - strVar[dstno]; // #chars -> #bytes + src = advance(src, srcpos); + len = advance(src, len) - src; // #chars -> #bytes + + strVar[dstno] = realloc(strVar[dstno], dstpos + len + 1); + strncpy(strVar[dstno] + dstpos, src, len); + strVar[dstno][dstpos + len] = '\0'; + + if (buf) + free(buf); } /* 文字変数への接続 */ -char *v_strcat(int no, const char *str) { - return strncat(strVar + no * strvar_len, str, strvar_len - 1); +void v_strcat(int no, const char *str) { + if (no < 0 || no >= strvar_cnt) { + WARNING("string index out of range: %d", no); + return; + } + if (!strVar[no]) { + strVar[no] = strdup(str); + return; + } + int len1 = strlen(strVar[no]); + int len2 = strlen(str); + strVar[no] = realloc(strVar[no], len1 + len2 + 1); + strcpy(strVar[no] + len1, str); } /* 文字変数の長さ */ size_t v_strlen(int no) { - return strlen(strVar + no * strvar_len); + if (no < 0 || no >= strvar_cnt) { + WARNING("string index out of range: %d", no); + return 0; + } + return strVar[no] ? sjis_count_char(strVar[no]) : 0; } /* 文字変数そのもの */ -char *v_str(int no) { - return strVar + no * strvar_len; +const char *v_str(int no) { + if (no < 0 || no >= strvar_cnt) { + WARNING("string index out of range: %d", no); + return ""; + } + return strVar[no] ? strVar[no] : ""; +} + +int v_strstr(int no, int start, const char *str) { + if (no < 0 || no >= strvar_cnt) { + WARNING("string index out of range: %d", no); + return -1; + } + if (!*str) + return 0; + if (!strVar[no]) + return -1; + const char *p = advance(strVar[no], start); + const char *found = strstr(p, str); + if (!found) + return -1; + int n = start; + while (p < found) { + p += CHECKSJIS1BYTE(*p) ? 2 : 1; + n++; + } + return n; +} + +void v_strFromVars(int no, const int *vars) { + if (no < 0 || no >= strvar_cnt) { + WARNING("string index out of range: %d", no); + return; + } + int len = 0; + for (const int *c = vars; *c; c++) + len += (*c < 256) ? 1 : 2; + + if (strVar[no]) + free(strVar[no]); + char *p = strVar[no] = malloc(len + 1); + + for (const int *v = vars; *v; v++) { + if (*v < 256) { + *p++ = *v; + } else { + *p++ = *v & 0xff; + *p++ = *v >> 8; + } + } + *p = '\0'; +} + +int v_strToVars(int no, int *vars) { + if (no < 0 || no >= strvar_cnt) { + WARNING("string index out of range: %d", no); + return 0; + } + if (!strVar[no]) { + *vars = 0; + return 1; + } + + int count = 0; + for (const char *p = strVar[no]; *p; count++) { + vars[count] = *p++ & 0xff; + if (CHECKSJIS1BYTE(vars[count])) + vars[count] |= (*p++ & 0xff) << 8; + } + vars[count++] = 0; + return count; } #ifdef DEBUG diff --git a/src/variable.h b/src/variable.h index 5cf7762..e7119aa 100644 --- a/src/variable.h +++ b/src/variable.h @@ -60,9 +60,13 @@ extern int v_getArrayBufferCnt(int page); extern boolean v_getArrayBufferStatus(int page); extern void v_initStringVars(int ,int ); extern boolean v_initVars(); -extern char *v_strcpy(int no, const char *str); -extern char *v_strcat(int no, const char *str); +extern void v_strcpy(int no, const char *str); +extern void v_strncpy(int dstno, int dstpos, int srcno, int srcpos, int len); +extern void v_strcat(int no, const char *str); extern size_t v_strlen(int no); -extern char *v_str(int no); +extern int v_strstr(int no, int start, const char *str); +extern void v_strFromVars(int no, const int *vars); +extern int v_strToVars(int no, int *vars); +extern const char *v_str(int no); #endif /* !__VARIABLE__ */