📄 files.c
字号:
/* Classic Ladder Project *//* Copyright (C) 2001 Marc Le Douarain *//* mavati@club-internet.fr *//* http://www.multimania.com/mavati/classicladder *//* February 2001 *//* Last update : 17 August 2002 *//* ------------------------------------------------------------------------------------- *//* Load/Save Rungs , Timers , Monostables , Arithmetic expressions & Sections parameters *//* ------------------------------------------------------------------------------------- *//* This library is free software; you can redistribute it and/or *//* modify it under the terms of the GNU Lesser General Public *//* License as published by the Free Software Foundation; either *//* version 2.1 of the License, or (at your option) any later version. *//* This library 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 *//* Lesser General Public License for more details. *//* You should have received a copy of the GNU Lesser General Public *//* License along with this library; if not, write to the Free Software *//* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <dirent.h>#include <errno.h>// for mkdir( ) Linux#include <sys/stat.h>#include <sys/types.h>#include "classicladder.h"#include "global.h"#include "vars_access.h"#include "manager.h"#include "calc.h"#include "edit.h"#include "files.h"#ifdef debug#define dbg_printf printf#elsestatic inline int dbg_printf(char *f, ...){ return 0;}#endifchar TmpDirectory[400];StrDatasForBase CorresDatasForBase[3] = { {BASE_MINS, TIME_BASE_MINS, "%.1fmn", "Mins"},{BASE_SECS, TIME_BASE_SECS, "%.1fs", "Secs"},{BASE_100MS, TIME_BASE_100MS, "%.0f00ms", "100msecs"}};char ConvRawLineOfElements(char *RawLine, int y, StrRung * StorageRung){ char *StartOfValue; char *EndOfValue; int x = 0; char EndOfLine; StartOfValue = RawLine; EndOfValue = RawLine; do { /* Extract Element Type */ StartOfValue = EndOfValue; do { EndOfValue++; } while (*EndOfValue != '-'); *EndOfValue++ = '\0'; StorageRung->Element[x][y].Type = atoi(StartOfValue); /* Extract ConnectedWithTop */ StartOfValue = EndOfValue; do { EndOfValue++; } while (*EndOfValue != '-'); *EndOfValue++ = '\0'; StorageRung->Element[x][y].ConnectedWithTop = atoi(StartOfValue); /* Extract Var Type */ StartOfValue = EndOfValue; do { EndOfValue++; } while (*EndOfValue != '/'); *EndOfValue++ = '\0'; StorageRung->Element[x][y].VarType = atoi(StartOfValue); /* Extract Var Offset in the type table */ StartOfValue = EndOfValue; do { EndOfValue++; } while ((*EndOfValue != ',') && (*EndOfValue != 10)); EndOfLine = TRUE; if (*EndOfValue == ',') EndOfLine = FALSE; *EndOfValue++ = '\0'; StorageRung->Element[x][y].VarNum = atoi(StartOfValue); /* Next Element */ x++; } while (!EndOfLine); return (x);}char LoadRung(char *FileName, StrRung * BufRung){ FILE *File; char Okay = FALSE; char Line[300]; char *LineOk; int y = 0; File = fopen(FileName, "rt"); if (File) { do { LineOk = fgets(Line, 300, File); if (LineOk) { char FndElements; switch (Line[0]) { case ';': break; case '#': if (strncmp(&Line[1], "VER=", 4) == 0) { if (atoi(&Line[5]) > 2) { printf("Rung version not supported...\n"); LineOk = FALSE; } } if (strncmp(&Line[1], "LABEL=", 6) == 0) { strcpy(BufRung->Label, &Line[7]); if (strlen(BufRung->Label) > 0 && BufRung->Label[strlen(BufRung->Label) - 1] == '\n') BufRung->Label[strlen(BufRung->Label) - 1] = '\0'; if (strlen(BufRung->Label) > 0 && BufRung->Label[strlen(BufRung->Label) - 1] == '\r') BufRung->Label[strlen(BufRung->Label) - 1] = '\0'; if (strlen(BufRung->Label) > 0 && BufRung->Label[strlen(BufRung->Label) - 1] == '\r') BufRung->Label[strlen(BufRung->Label) - 1] = '\0'; } if (strncmp(&Line[1], "COMMENT=", 8) == 0) { strcpy(BufRung->Comment, &Line[9]); if (strlen(BufRung->Comment) > 0 && BufRung->Comment[strlen(BufRung->Comment) - 1] == '\n') BufRung->Comment[strlen(BufRung->Comment) - 1] = '\0'; if (strlen(BufRung->Comment) > 0 && BufRung->Comment[strlen(BufRung->Comment) - 1] == '\r') BufRung->Comment[strlen(BufRung->Comment) - 1] = '\0'; if (strlen(BufRung->Comment) > 0 && BufRung->Comment[strlen(BufRung->Comment) - 1] == '\r') BufRung->Comment[strlen(BufRung->Comment) - 1] = '\0'; } if (strncmp(&Line[1], "PREVRUNG=", 9) == 0) BufRung->PrevRung = atoi(&Line[10]); if (strncmp(&Line[1], "NEXTRUNG=", 9) == 0) BufRung->NextRung = atoi(&Line[10]); break; default: FndElements = ConvRawLineOfElements(Line, y, BufRung); y++; } } } while (LineOk); fclose(File); Okay = TRUE; } return (Okay);}char SaveRung(char *FileName, StrRung * BufRung){ FILE *File; char Okay = FALSE; int x, y; File = fopen(FileName, "wt"); if (File) { fprintf(File, "; Rung :\n"); fprintf(File, "; all the blocks with the following format :\n"); fprintf(File, "; type (see classicladder.h) - ConnectedWithTop - VarType (see classicladder.h) / VarOffset\n"); fprintf(File, "#VER=2.0\n"); fprintf(File, "#LABEL=%s\n", BufRung->Label); fprintf(File, "#COMMENT=%s\n", BufRung->Comment); fprintf(File, "#PREVRUNG=%d\n", BufRung->PrevRung); fprintf(File, "#NEXTRUNG=%d\n", BufRung->NextRung); for (y = 0; y < RUNG_HEIGHT; y++) { for (x = 0; x < RUNG_WIDTH; x++) { fprintf(File, "%d-%d-%d/%d", BufRung->Element[x][y].Type, BufRung->Element[x][y].ConnectedWithTop, BufRung->Element[x][y].VarType, BufRung->Element[x][y].VarNum); if (x < RUNG_WIDTH - 1) fprintf(File, " , "); } fprintf(File, "\n"); } fclose(File); Okay = TRUE; } return (Okay);}void LoadAllRungs_V1(char *BaseName, StrRung * Rungs, int *TheFirst, int *TheLast, int *TheCurrent){ int NumRung; StrRung *PrevRung = NULL; int PrevNumRung = 0; *TheFirst = -1; *TheCurrent = -1; for (NumRung = 0; NumRung < NBR_RUNGS; NumRung++) { char RungFile[400]; sprintf(RungFile, "%s%d.csv", BaseName, NumRung); dbg_printf("Loading file : %s", RungFile); if (LoadRung(RungFile, Rungs)) { if (*TheFirst == -1) { *TheFirst = NumRung; *TheCurrent = NumRung; } if (PrevRung) { PrevRung->NextRung = NumRung; } Rungs->Used = TRUE; Rungs->PrevRung = PrevNumRung; *TheLast = NumRung; PrevNumRung = NumRung; PrevRung = Rungs; dbg_printf(" - ok.\n"); } else dbg_printf(" - not found.\n"); // DumpRung(Rungs); Rungs++; } /* no rungs loaded ? */ /* we must keep at least one empty ! */ if (*TheFirst < 0) { *TheFirst = 0; *TheCurrent = 0; }}void LoadAllRungs(char *BaseName, StrRung * Rungs){ int NumRung; for (NumRung = 0; NumRung < NBR_RUNGS; NumRung++) { char RungFile[400]; sprintf(RungFile, "%s%d.csv", BaseName, NumRung); dbg_printf("Loading file : %s", RungFile); if (LoadRung(RungFile, Rungs)) { Rungs->Used = TRUE; dbg_printf(" - ok.\n"); } else dbg_printf(" - not found.\n"); // DumpRung(Rungs); Rungs++; }}void SaveAllRungs(char *BaseName){ int NumRung; char RungFile[400]; /* delete all before */ for (NumRung = 0; NumRung < NBR_RUNGS; NumRung++) { sprintf(RungFile, "%s%d.csv", BaseName, NumRung); unlink(RungFile); } /* save rungs (only defined ones are saved) */ /* Since v0.5.5, the number of the rungs do not change : */ /* it's easier, and with the sections added it's indispensable */ for (NumRung = 0; NumRung < NBR_RUNGS; NumRung++) { if (RungArray[NumRung].Used) { sprintf(RungFile, "%s%d.csv", BaseName, NumRung); dbg_printf("Saving file : %s", RungFile); if (SaveRung(RungFile, &RungArray[NumRung])) dbg_printf(" - ok.\n"); else dbg_printf(" - failed.\n"); } }}void DumpRung(StrRung * TheRung){ int x, y; printf("Used=%d\n", TheRung->Used); for (y = 0; y < RUNG_HEIGHT; y++) { for (x = 0; x < RUNG_WIDTH; x++) { printf("%d:%d:%d=%d , ", TheRung->Element[x][y].Type, TheRung->Element[x][y].ConnectedWithTop, TheRung->Element[x][y].VarNum, TheRung->Element[x][y].DynamicOutput); } printf("\n"); }}/* FIXME - this prints a message when a file is missing, but doesn't do anything else. Better error handling is needed */ static void check_file ( char *file ){ struct stat stat_buf; if ( stat(file, &stat_buf) != 0 ) { printf ( "File '%s' not found\n", file ); }}static void LoadAllLadderDatas(char *DatasDirectory){ char FileName[500]; InitAllLadderDatas(); sprintf(FileName, "%s/timers.csv", DatasDirectory); check_file(FileName); printf("Loading timers datas from %s\n", FileName); LoadTimersParams(FileName, TimerArray); sprintf(FileName, "%s/monostables.csv", DatasDirectory); check_file(FileName); printf("Loading monostables datas from %s\n", FileName); LoadMonostablesParams(FileName, MonostableArray); PrepareTimers(); PrepareMonostables(); sprintf(FileName, "%s/arithmetic_expressions.csv", DatasDirectory); check_file(FileName); printf("Loading arithmetic expressions from %s\n", FileName); LoadArithmeticExpr(FileName); // Sections added since v0.5.5, the format of files has a little changed // : // before the prev/next rungs were not saved in each rung... // and the nmber of rungs changed when saved... sprintf(FileName, "%s/sections.csv", DatasDirectory); check_file(FileName); printf("Loading sections datas from %s\n", FileName); if (LoadSectionsParams(FileName)) { check_file(FileName); sprintf(FileName, "%s/rung_", DatasDirectory); LoadAllRungs(FileName, RungArray); } else { printf("Rungs with old format found (no sections)\n"); sprintf(FileName, "%s/rung_", DatasDirectory); check_file(FileName); LoadAllRungs_V1(FileName, RungArray, &InfosGene->FirstRung, &InfosGene->LastRung, &InfosGene->CurrentRung); // if we load old format files, sections wasn't created, so we must // write theses infos... SectionArray[0].FirstRung = InfosGene->FirstRung; SectionArray[0].LastRung = InfosGene->LastRung; }#ifdef SEQUENTIAL_SUPPORT sprintf(FileName, "%s/sequential.csv", DatasDirectory); check_file(FileName); printf("Loading sequential datas from %s\n", FileName); LoadSequential(FileName);#endif PrepareRungs();#ifdef SEQUENTIAL_SUPPORT PrepareSequential();#endif}static void SaveAllLadderDatas(char *DatasDirectory){ char FileName[500]; sprintf(FileName, "%s/timers.csv", DatasDirectory); SaveTimersParams(FileName, TimerArray); sprintf(FileName, "%s/monostables.csv", DatasDirectory); SaveMonostablesParams(FileName, MonostableArray); sprintf(FileName, "%s/arithmetic_expressions.csv", DatasDirectory); SaveArithmeticExpr(FileName); sprintf(FileName, "%s/rung_", DatasDirectory); SaveAllRungs(FileName); sprintf(FileName, "%s/sections.csv", DatasDirectory); SaveSectionsParams(FileName);#ifdef SEQUENTIAL_SUPPORT sprintf(FileName, "%s/sequential.csv", DatasDirectory); SaveSequential(FileName);#endif}void ConvRawLineOfNumbers(char *RawLine, char NbrParams, int *ValuesFnd){ char *StartOfValue; char *EndOfValue; char Num = 0; char EndOfLine; StartOfValue = RawLine; EndOfValue = RawLine; EndOfLine = FALSE; do { /* Extract Value */ StartOfValue = EndOfValue; do { EndOfValue++; } while ((*EndOfValue != ',') && (*EndOfValue != 10)); if (*EndOfValue == 10) EndOfLine = TRUE; *EndOfValue++ = '\0'; *ValuesFnd++ = atoi(StartOfValue); Num++; StartOfValue = EndOfValue; } while ((!EndOfLine) && (Num < NbrParams));}int ConvBaseInMilliSecsToId(int NbrMilliSecs){ switch (NbrMilliSecs) { case TIME_BASE_MINS: return BASE_MINS; case TIME_BASE_SECS: return BASE_SECS; case TIME_BASE_100MS: return BASE_100MS; default: printf("!!!Error in ConvBaseInMilliSecsToInt()\n"); return BASE_SECS; }}char LoadTimersParams(char *FileName, StrTimer * BufTimers){ FILE *File; char Okay = FALSE; char Line[300]; char *LineOk; int Params[3]; File = fopen(FileName, "rt"); if (File) { do { LineOk = fgets(Line, 300, File); if (LineOk) { if (Line[0] != ';') { ConvRawLineOfNumbers(Line, 2, Params); switch (Params[0]) { case BASE_MINS: case BASE_SECS: case BASE_100MS: BufTimers->Base = CorresDatasForBase[Params[0]].ValueInMS; BufTimers->Preset = Params[1] * BufTimers->Base; strcpy(BufTimers->DisplayFormat, CorresDatasForBase[Params[0]].DisplayFormat); break; default: BufTimers->Base = 1; BufTimers->Preset = 10; strcpy(BufTimers->DisplayFormat, "%f?"); printf("!!! Error loading parameter base in %s\n", FileName); break; } dbg_printf("Timer => Base = %d , Preset = %d\n", BufTimers->Base, BufTimers->Preset); BufTimers++; } } } while (LineOk); fclose(File); Okay = TRUE; } return (Okay);}char SaveTimersParams(char *FileName, StrTimer * BufTimers){ FILE *File; char Okay = FALSE; int NumTimer = 0; printf("Saving timer params file=%s", FileName); File = fopen(FileName, "wt"); if (File) { fprintf(File, "; Timers :\n"); fprintf(File, "; Base(see classicladder.h),Preset\n"); do { fprintf(File, "%d,%d\n", ConvBaseInMilliSecsToId(BufTimers->Base),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -