/* * variable.c 変数管理 * * Copyright (C) 1997-1998 Masaki Chikama (Wren) * 1998- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* $Id: variable.c,v 1.15 2002/09/18 13:16:22 chikama Exp $ */ #include #include #include #include "portab.h" #include "utfsjis.h" #include "variable.h" #include "xsystem35.h" typedef struct { int *pointvar; int page; int offset; } VariableAttributes; /* システム変数 */ int sysVar[SYSVAR_MAX]; /* 配列変数の情報 */ static VariableAttributes attributes[SYSVAR_MAX]; /* 配列本体 */ arrayVarBufferStruct arrayVarBuffer[ARRAYVAR_PAGEMAX]; /* 64bit変数 */ double longVar[SYSVARLONG_MAX]; /* 文字列変数 */ static char **strVar; /* 文字列変数の属性(最大,1つあたりの大きさ) */ int strvar_cnt; int strvar_len; int preVarPage; /* 直前にアクセスした変数のページ */ int preVarIndex; /* 直前にアクセスした変数のINDEX */ int preVarNo; /* 直前にアクセスした変数の番号 */ const char *v_name(int var) { if (var < nact->ain.varnum) return nact->ain.var[var]; static char buf[10]; sprintf(buf, "VAR%d", var); return buf; } static char *advance(const char *s, int n) { while (*s && n > 0) { s = advance_char(s, nact->encoding); n--; } return (char *)s; } int *v_ref(int var) { VariableAttributes *attr = &attributes[var]; preVarPage = attr->page; preVarNo = var; if (attr->page == 0) { // Normal variable access preVarIndex = var; return sysVar + var; } // Implicit array access int *index = attr->pointvar; int page = attr->page; int offset = attr->offset; if (*index + offset >= arrayVarBuffer[page - 1].size) return NULL; preVarIndex = offset + *index; return arrayVarBuffer[page - 1].value + offset + *index; } int *v_ref_indexed(int var, int index) { VariableAttributes *attr = &attributes[var]; preVarPage = attr->page; preVarNo = var; if (attr->page == 0) { // If VAR_n is not an array variable, VAR_n[i] points to VAR_(n+i). if ((var + index) >= SYSVAR_MAX) return NULL; preVarIndex = var + index; return sysVar + var + index; } // Indexed array access int page = attr->page; int offset = attr->offset; if (offset + index >= arrayVarBuffer[page - 1].size) return NULL; preVarIndex = offset + index; return arrayVarBuffer[page - 1].value + offset + index; } /* 配列バッファの確保 DC ,page = 1~ */ extern boolean v_allocateArrayBuffer(int page, int size, boolean saveflag) { if (page <= 0 || page > 256) { return false; } if (size <= 0 || size > 65536) { return false; } void *buf = arrayVarBuffer[page - 1].value; if (buf != NULL) buf = realloc(buf, size * sizeof(int)); else buf = calloc(size, sizeof(int)); if (!buf) NOMEMERR(); arrayVarBuffer[page - 1].value = buf; arrayVarBuffer[page - 1].size = size; arrayVarBuffer[page - 1].saveflag = saveflag; return true; } /* 配列変数の割り当て DS */ extern boolean v_defineArrayVar(int datavar, int *pointvar, int offset, int page) { if (datavar < 0 || datavar > SYSVAR_MAX - 1) { return false; } if (page < 0 || page > ARRAYVAR_PAGEMAX - 1) { return false; } if (offset < 0 || offset >= arrayVarBuffer[page - 1].size) { return false; } attributes[datavar].pointvar = pointvar; attributes[datavar].page = page; attributes[datavar].offset = offset; return true; } /* 配列変数の割り当て解除 DR */ extern boolean v_releaseArrayVar(int datavar) { attributes[datavar].page = 0; return true; } /* 指定ページは使用中 page = 1~ */ extern boolean v_getArrayBufferStatus(int page) { return (arrayVarBuffer[page - 1].value != NULL) ? true : false; } /* 文字列変数の再初期化 */ extern void svar_init(int max_index, int len) { for (int i = max_index + 1; i < strvar_cnt; i++) { if (strVar[i]) free(strVar[i]); } strVar = realloc(strVar, (max_index + 1) * sizeof(char *)); if (strVar == NULL) { NOMEMERR(); } for (int i = strvar_cnt; i <= max_index; i++) strVar[i] = NULL; strvar_cnt = max_index + 1; strvar_len = len; } extern int svar_maxindex(void) { return strvar_cnt - 1; } /* 変数の初期化 */ void v_init(void) { svar_init(STRVAR_MAX - 1, STRVAR_LEN); } void v_reset(void) { memset(sysVar, 0, sizeof(sysVar)); memset(attributes, 0, sizeof(attributes)); memset(longVar, 0, sizeof(longVar)); for (int i = 0; i < ARRAYVAR_PAGEMAX; i++) { if (arrayVarBuffer[i].value) free(arrayVarBuffer[i].value); } memset(arrayVarBuffer, 0, sizeof(arrayVarBuffer)); for (int i = 0; i < strvar_cnt; i++) { if (strVar[i]) { free(strVar[i]); strVar[i] = NULL; } } svar_init(STRVAR_MAX - 1, STRVAR_LEN); } /* 文字変数への代入 */ void svar_set(int no, const char *str) { if ((unsigned)no >= strvar_cnt) { WARNING("string index out of range: %d\n", no); return; } if (strVar[no]) free(strVar[no]); strVar[no] = strdup(str); } void svar_copy(int dstno, int dstpos, int srcno, int srcpos, int len) { if ((unsigned)dstno >= strvar_cnt) { WARNING("string index out of range: %d\n", dstno); return; } if (!strVar[dstno]) strVar[dstno] = strdup(""); char *buf = NULL; const char *src; if (srcno == dstno) src = buf = strdup(strVar[srcno]); else src = svar_get(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); } /* 文字変数への接続 */ void svar_append(int no, const char *str) { if ((unsigned)no >= strvar_cnt) { WARNING("string index out of range: %d\n", 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 svar_length(int no) { const char *s = svar_get(no); int c = 0; while (*s) { s = advance_char(s, nact->encoding); c++; } return c; } /* Width of a string (2 for full-width characters, 1 for half-width) */ int svar_width(int no) { return strlen(svar_get(no)); } /* 文字変数そのもの */ const char *svar_get(int no) { if ((unsigned)no >= strvar_cnt) { WARNING("string index out of range: %d\n", no); return ""; } return strVar[no] ? strVar[no] : ""; } int svar_find(int no, int start, const char *str) { if ((unsigned)no >= strvar_cnt) { WARNING("string index out of range: %d\n", 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 = 0; while (p < found) { p = advance_char(p, nact->encoding); n++; } return n; } void svar_fromVars(int no, const int *vars) { if ((unsigned)no >= strvar_cnt) { WARNING("string index out of range: %d\n", 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 svar_toVars(int no, int *vars) { if ((unsigned)no >= strvar_cnt) { WARNING("string index out of range: %d\n", no); return 0; } if (!strVar[no]) { *vars = 0; return 1; } int count = 0; for (const char *p = strVar[no]; *p; p++, count++) { vars[count] = *p & 0xff; if (CHECKSJIS1BYTE(*p) && *(p + 1)) vars[count] |= (*++p & 0xff) << 8; } vars[count++] = 0; return count; } int svar_getCharType(int no, int pos) { const char *p = svar_get(no); for (; *p && pos > 0; pos--) p += CHECKSJIS1BYTE(*p) ? 2 : 1; if (!*p) return 0; return CHECKSJIS1BYTE(*p) ? 2 : 1; } void svar_replaceAll(int no, int pattern, int replacement) { const char *pat = svar_get(pattern); if (!*pat) return; const char *repl = svar_get(replacement); if ((unsigned)no >= strvar_cnt) { WARNING("string index out of range: %d\n", no); return; } if (!strVar[no]) return; char *src = strVar[no]; strVar[no] = NULL; char *start = src, *found;; while ((found = strstr(start, pat))) { char bak = *found; *found = '\0'; svar_append(no, start); *found = bak; svar_append(no, repl); start = found + strlen(pat); } svar_append(no, start); free(src); }