Byte *allocmem( Dword reqsize ) { MemBlock *BlockForCheck; MemBlock *LastKnownGood; Dword tail; Byte *address; //подровняем размер if( ( tail = reqsize % SIZE_ALIGN ) != 0 ) { reqsize += SIZE_ALIGN - tail; } LastKnownGood = NULL; // ждём освобождения мьютекса while ( rtlInterlockedExchange( &mmMutex, TRUE ) ) { // kos_Pause( 1 ); } //ищем подходящий свободный блок if( rootfree != NULL ) { for ( BlockForCheck = rootfree; ; BlockForCheck = BlockForCheck->Next ) { if ( BlockForCheck->Size >= reqsize ) { //нашли if ( LastKnownGood != NULL ) { if ( LastKnownGood->Size >= BlockForCheck->Size ) LastKnownGood = BlockForCheck; } else LastKnownGood = BlockForCheck; if ( LastKnownGood->Size == reqsize ) break; } if ( BlockForCheck->Next == NULL ) break; } } if ( LastKnownGood != NULL ) { //проверим найденный блок на возможность деления tail = LastKnownGood->Size - reqsize; if ( tail >= ( sizeof(MemBlock) + SIZE_ALIGN ) ) { //будем разбивать BlockForCheck = (MemBlock *)( ( (Byte *)LastKnownGood ) + tail ); BlockForCheck->Size = reqsize; //вставим занятый блок в начало списка занатых блоков if( rootuser != NULL ) { BlockForCheck->Next = rootuser; rootuser->Previous = BlockForCheck; BlockForCheck->Previous = NULL; rootuser = BlockForCheck; } else { rootuser = BlockForCheck; BlockForCheck->Next = NULL; BlockForCheck->Previous = NULL; } //изменим размер оставшейся части LastKnownGood->Size = tail - sizeof(MemBlock); address = ( (Byte *)BlockForCheck ) + sizeof(MemBlock); // отпустим мьютекс rtlInterlockedExchange( &mmMutex, FALSE ); return address; } else { //перемести блок из очереди свободных в начало очереди занятых //сначала выкинем его из очереди свободных if ( LastKnownGood->Previous != NULL ) { LastKnownGood->Previous->Next = LastKnownGood->Next; } else { //блок стоит в начале очереди rootfree = LastKnownGood->Next; } if( LastKnownGood->Next != NULL ) { LastKnownGood->Next->Previous = LastKnownGood->Previous; } //теперь вставим его в очередь занятых if( rootuser != NULL ) { LastKnownGood->Next = rootuser; rootuser->Previous = LastKnownGood; LastKnownGood->Previous = NULL; rootuser = LastKnownGood; } else { rootuser = LastKnownGood; LastKnownGood->Next = NULL; LastKnownGood->Previous = NULL; } // address = ( (Byte *)LastKnownGood ) + sizeof(MemBlock); // отпустим мьютекс rtlInterlockedExchange( &mmMutex, FALSE ); return address; } } else { // надо получить ещё блок памяти LastKnownGood = (MemBlock *)kos_malloc( (reqsize > 0x10000 - sizeof(MemBlock)) ? (reqsize + sizeof(MemBlock)) : 0x10000); if (LastKnownGood != NULL) { LastKnownGood->Size = reqsize; // теперь вставим его в очередь занятых LastKnownGood->Next = rootuser; LastKnownGood->Previous = NULL; if (rootuser != NULL) rootuser->Previous = LastKnownGood; rootuser = LastKnownGood; // а также добавим хвост свежевыделенного большого блока в список свободных if (reqsize < 0x10000 - sizeof(MemBlock)) { MemBlock* free = (MemBlock*)((Byte*)LastKnownGood + sizeof(MemBlock) + reqsize); free->Next = rootfree; free->Previous = NULL; if (rootfree != NULL) rootfree->Previous = free; rootfree = free; } address = (Byte*)LastKnownGood + sizeof(MemBlock); // отпустим мьютекс rtlInterlockedExchange(&mmMutex, FALSE); return address; } } // отпустим мьютекс rtlInterlockedExchange( &mmMutex, FALSE ); // rtlDebugOutString( "allocmem failed." ); kos_ExitApp(); // return NULL; }
int LoadCSV(char *fname) { // clear the table reinit(); kosFileInfo fileInfo; strcpy(fileInfo.fileURL,fname); fileInfo.OffsetLow = 0; fileInfo.OffsetHigh = 0; char *line; int col = 1, row = 1; int code = 0; do { line = Kos_FileRead(fileInfo, code); if (!line || *line == '\0' || (code != 0 && code != 6)) { sprintf(debuf, "read end, line not null = %U, code = %U", !line, code); rtlDebugOutString(debuf); break; } sprintf(debuf, "read '%S' len %U", line, strlen(line)); rtlDebugOutString(debuf); // разборать строку // выделить ;, причем вне " int i = 0; while (i <= strlen(line)) { int inPar = 0; // inPar: 0 - не кавычки, 1 - только что была кавычка, 2 - кавычка была, но давно int start = i; while (i <= strlen(line)) { char c = line[i]; if (!c) c = ';'; int yes_semicolon = 0; switch (inPar) { case 0: if (c == '\"') { inPar = 1; } else { if (c == ';') yes_semicolon = 1; } break; case 1: inPar = 2; break; case 2: if (c == '\"') // она закрылась { inPar = 0; } /*else { if (c == ';') yes_semicolon = 1; }*/ break; } if (yes_semicolon) { // итак, line[i] = ';' int tmp = line[start] == '"' ? 1 : 0; int sz = i - start - tmp * 2; if (sz > 0) { cells[col][row] = (char *)allocmem(sz + 1); memset((Byte*)cells[col][row], 0, sz + 1); int m = 0; for (int l = 0; l < sz; l++) { if (line[start + tmp + l] == '\"') { cells[col][row][m++] = '\"'; l++; // пропустить следующую кавычку } else cells[col][row][m++] = line[start + tmp + l]; } sprintf(debuf, "set %U %U = '%S'", col, row, cells[col][row]); rtlDebugOutString(debuf); } start = i + 1; col++; } i++; } row++; col = 1; i++; } } while(line); return 1; }
double calc_callback(char *str) { int i,j,x,y; if (abort_calc == 1) return 0.0; //rtlDebugOutString(str); if (*str == '$') str++; for (i = 0; i < strlen(str); i++) if (str[i] >= '0' && str[i] <= '9') break; if (str[i-1] == '$') i--; if (i == strlen(str)) { abort_calc = 1; serror(ERR_BADVARIABLE); return 0.0; } x = -1; for (j = 0; j < col_count; j++) // if (strnicmp(str,cells[j][0],i-1)==0) if (str[0] == cells[j][0][0] && ((i == 1) || (str[1] == cells[j][0][1]))) { x = j; break; } if (str[i] == '$') i++; y = -1; for (j = 0; j < row_count; j++) if (strcmp(str+i,cells[0][j])==0) { y = j; break; } if (x == -1 || y == -1) { abort_calc = 1; serror(ERR_BADVARIABLE); return 0.0; } double hold; if (values[x][y]) if (values[x][y][0] == '#') { serror(ERR_BADVARIABLE); abort_calc = 1; } else { hold = atof(values[x][y]); //if (convert_error) // нереальный случай... //{ // serror(ERR_BADVARIABLE); // abort_calc = 1; //} } else { if (cells[x][y]) { hold = atof(cells[x][y]); if (convert_error == ERROR || convert_error == ERROR_END) { serror(ERR_BADVARIABLE); abort_calc = 1; } } else { sprintf(debuf, "bad var %S", str); rtlDebugOutString(debuf); serror(ERR_BADVARIABLE); abort_calc = 1; } } return hold; }
int SaveCSV(char *fname) { int i, j; int min_col = col_count, min_row = row_count, max_row = -1, max_col = -1; int first = 1; kosFileInfo fileInfo; memset((Byte*)&fileInfo, 0, sizeof(fileInfo)); strcpy(fileInfo.fileURL,fname); fileInfo.OffsetLow = 0; fileInfo.OffsetHigh = 0; fileInfo.rwMode = 8; // delete rtlDebugOutString("savecsv: old file deleted"); for (i = 1; i < col_count; i++) { for (j = 1; j < row_count; j++) { if (cells[i][j]) { min_col = min(min_col, i); min_row = min(min_row, j); max_col = max(max_col, i); max_row = max(max_row, j); } } } sprintf(debuf, "col %U %U row", min_col, max_col, min_row, max_row); rtlDebugOutString(debuf); for (j = min_row; j <= max_row; j++) { char buffer[1024]; // не надо так делать int buf_len = 0; memset((Byte*)buffer, 0, 1024); for (i = min_col; i <= max_col; i++) { char *cur = values[i][j] ? values[i][j] : cells[i][j]; if (cur) { buffer[buf_len++] = '\"'; for (int k = 0; k < strlen(cur); k++) { if (cur[k] == '\"') buffer[buf_len++] = '\"'; // кавычек - по две buffer[buf_len++] = cur[k]; } buffer[buf_len++] = '\"'; } buffer[buf_len++] = ';'; } rtlDebugOutString(buffer); // очередная строка теперь в буфере buffer[buf_len++] = '\n'; if (!Kos_FileWrite(fileInfo, buffer, first ? (first = 0, 2) : 3)) return 0; } return 1; }