16#include <miktex/C4P/config.h>
32#include <miktex/App/Application>
34#include <miktex/Core/File>
35#include <miktex/Core/IntegerTypes>
36#include <miktex/Core/Session>
38#include <miktex/Util/StringUtil>
49typedef MIKTEX_INT16 C4P_signed16;
50typedef MIKTEX_INT32 C4P_signed32;
51typedef MIKTEX_INT64 C4P_signed64;
52typedef MIKTEX_INT8 C4P_signed8;
53typedef MIKTEX_UINT16 C4P_unsigned16;
54typedef MIKTEX_UINT32 C4P_unsigned32;
55typedef MIKTEX_UINT64 C4P_unsigned64;
56typedef MIKTEX_UINT8 C4P_unsigned8;
58typedef int C4P_integer;
59typedef MIKTEX_INT64 C4P_longinteger;
61#if defined(C4P_REAL_IS_DOUBLE)
62typedef double C4P_real;
64typedef float C4P_real;
67typedef double C4P_longreal;
70typedef bool C4P_boolean;
79 void AssertValid()
const
81 MIKTEX_ASSERT(file !=
nullptr);
87 FILE* file = this->file;
89 if ((flags & NotOwner) != 0)
91 std::shared_ptr<MiKTeX::Core::Session> session = MIKTEX_SESSION();
92 session->CloseFile(file);
96 void Attach(FILE* file,
bool takeOwnership)
124 FILE* file =
nullptr;
125 enum { NotOwner = 0x00000001 };
136 typedef T ElementType;
138 void PascalFileIO(
bool turnOn)
150 bool IsPascalFileIO()
const
152 return (flags & Buffered) != 0;
155 const ElementType& bufref()
const
157 MIKTEX_EXPECT(IsPascalFileIO());
158 return currentElement;
161 ElementType& bufref()
164 return currentElement;
167 const ElementType& operator*()
const
172 ElementType& operator*()
184 if (IsPascalFileIO())
189 int lookAhead = getc(file);
191 if (lookAhead == EOF)
193 if (ferror(file) != 0)
195 MIKTEX_FATAL_CRT_ERROR_2(
"getc",
"path", path.ToString());
200 if (ungetc(lookAhead, file) != lookAhead)
202 MIKTEX_FATAL_CRT_ERROR_2(
"ungetc",
"path", path.ToString());
215 if (IsPascalFileIO())
217 return currentElement ==
'\r' || currentElement ==
'\n';
220 int lookAhead = getc(file);
222 if (lookAhead == EOF)
224 if (ferror(file) != 0)
226 MIKTEX_FATAL_CRT_ERROR_2(
"getc",
"path", path.ToString());
231 if (ungetc(lookAhead, file) != lookAhead)
233 MIKTEX_FATAL_CRT_ERROR_2(
"ungetc",
"path", path.ToString());
236 return lookAhead ==
'\r' || lookAhead ==
'\n';
239 void Read(ElementType* buf, std::size_t n)
241 std::size_t read = ReadInternal(buf, n);
244 MIKTEX_FATAL_ERROR_2(MIKTEXTEXT(
"Read operation failed."),
"path", path.ToString(),
"read", std::to_string(read),
"n", std::to_string(n));
246 if (IsPascalFileIO())
248 currentElement = buf[n - 1];
255 ReadInternal(¤tElement, 1);
274 MIKTEX_ASSERT(IsPascalFileIO());
275 if (fwrite(¤tElement,
sizeof(ElementType), 1, *
this) != 1 || ferror(*
this) != 0)
277 MIKTEX_FATAL_CRT_ERROR_2(
"fwrite",
"path", path.ToString());
281 void Seek(
long offset,
int origin)
284 if (fseek(*
this, offset, origin) != 0)
286 MIKTEX_FATAL_CRT_ERROR_2(
"fseek",
"path", path.ToString(),
"offset", std::to_string(offset),
"origin", std::to_string(origin));
288 if (IsPascalFileIO() && !(origin == SEEK_END && offset == 0))
296 enum { Buffered = 0x00010000 };
298 ElementType currentElement;
300 std::size_t ReadInternal(ElementType* buf, std::size_t n)
303 MIKTEX_ASSERT_BUFFER(buf, n);
304 if (feof(*
this) != 0)
306 MIKTEX_FATAL_ERROR_2(MIKTEXTEXT(
"Read operation failed: end of file reached"),
"path", path.ToString(),
"n", std::to_string(n));
308 size_t read = fread(buf,
sizeof(ElementType), n, *
this);
309 if (ferror(*
this) != 0)
311 MIKTEX_FATAL_CRT_ERROR_2(
"ferror",
"path", path.ToString());
315 MIKTEX_EXPECT(feof(*
this));
323#define C4P_FILE_STRUCT(Bt) C4P::BufferedFile<Bt>
329 C4PTHISAPI(C4P_real) GetReal();
330 C4PTHISAPI(
bool) IsTerminal();
331 C4PTHISAPI(
char) GetChar();
332 C4PTHISAPI(
int) GetInteger();
333 C4PTHISAPI(
void) DiscardLine();
336#define c4pargc GetArgC()
337#define c4pargv GetArgV()
339#define c4ppline GetCmdLine()
340#define c4pplen strlen(GetCmdLine())
342#define input (*(GetStdFilePtr(0)))
343#define output (*(GetStdFilePtr(1)))
344#define c4perroroutput (*(GetStdFilePtr(2)))
346class C4PTYPEAPI(ProgramBase)
351 C4PEXPORT MIKTEXTHISCALL ProgramBase();
352 C4PTHISAPI(
const char**) GetArgV();
353 C4PTHISAPI(
int) GetArgC();
354 C4PTHISAPI(
int) MakeCommandLine(
const std::vector<std::string>&args);
355 C4PTHISAPI(time_t) GetStartUpTime();
357 C4PTHISAPI(
void) SetStartUpTime(time_t time,
bool useUtc);
358 ProgramBase& operator=(ProgramBase && other) =
delete;
359 ProgramBase& operator=(
const ProgramBase& other) =
delete;
360 ProgramBase(ProgramBase && other) =
delete;
361 ProgramBase(
const ProgramBase& other) =
delete;
362 virtual C4PEXPORT MIKTEXTHISCALL ~ProgramBase() noexcept;
366 C4PTHISAPI(
C4P_text*) GetStdFilePtr(
unsigned idx);
367 C4PTHISAPI(const
char*) GetCmdLine();
368 C4PTHISAPI(
unsigned) GetDay();
369 C4PTHISAPI(
unsigned) GetHour();
370 C4PTHISAPI(
unsigned) GetMinute();
371 C4PTHISAPI(
unsigned) GetMonth();
372 C4PTHISAPI(
unsigned) GetSecond();
373 C4PTHISAPI(
unsigned) GetYear();
374 C4PTHISAPI(
void) Finish();
375 C4PTHISAPI(
void) Initialize(const
char* programName,
int argc,
char* argv[]);
377 template<class Ft>
void c4p_write_f(Ft&, Ft&)
381 template<
class Vt,
class Ft>
void c4p_write_v(Vt v, Ft& f)
388 template<
class Vt,
class Ft>
void c4p_write_c(Vt v, Ft& f)
394 template<
class Vt,
class Ft>
void c4p_write_c1(Vt v, Ft& f)
396 return c4p_write_c(v, f);
399 template<
class Vt,
class Ft>
void c4p_write_i(Vt v, Ft& f)
402 if (fprintf(f,
"%ld",
static_cast<long>(v)) < 0)
404 MIKTEX_FATAL_CRT_ERROR(
"fprintf");
408 template<
class Vt,
class Ft>
void c4p_write_i1(Vt v,
int w1, Ft& f)
411 if (fprintf(f,
"%*ld",
static_cast<int>(w1),
static_cast<long>(v)) < 0)
413 MIKTEX_FATAL_CRT_ERROR(
"fprintf");
417 template<
class Vt,
class Ft>
void c4p_write_i2(Vt v,
int w1,
int w2, Ft& f)
420 if (fprintf(f,
"%*.*ld",
static_cast<int>(w1),
static_cast<int>(w2),
static_cast<long>(v)) < 0)
422 MIKTEX_FATAL_CRT_ERROR(
"fprintf");
426 template<
class Vt,
class Ft>
void c4p_write_r(Vt v, Ft& f)
429 if (fprintf(f,
"%f",
static_cast<float>(v)) < 0)
431 MIKTEX_FATAL_CRT_ERROR(
"fprintf");
435 template<
class Vt,
class Ft>
void c4p_write_r2(Vt v,
int w1,
int w2, Ft& f)
438 if (fprintf(f,
"%*.*f",
static_cast<int>(w1),
static_cast<int>(w2),
static_cast<float>(v)) < 0)
440 MIKTEX_FATAL_CRT_ERROR(
"fprintf");
444 template <
class Vt,
class Ft>
void c4p_write_s(Vt v, Ft& f)
447 if (fputs(
reinterpret_cast<const char*
>(v), f) == EOF)
449 MIKTEX_FATAL_CRT_ERROR(
"fputs");
453 template<
class Ft>
void c4p_read_f(Ft&, Ft&)
457 template<
class Vt,
class Ft>
void c4p_read_v(Vt& v, Ft& f)
464 template<
class Vt,
class Ft>
void c4p_read_c(Vt& v, Ft& f)
470 template<
class Vt,
class Ft>
void c4p_read_i(Vt& v, Ft& f)
476 template<
class Vt,
class Ft>
void c4p_read_r(Vt& v, Ft& f)
482 const C4P_integer maxint = INT_MAX;
492 output.AssertValid();
493 if (putc(
'\n', output) == EOF)
495 MIKTEX_FATAL_CRT_ERROR(
"putc");
499 template<
class T>
void c4p_break(T& f)
502 if (fflush(f) == EOF)
504 MIKTEX_FATAL_CRT_ERROR(
"flush");
508 template<
class Ft>
void c4pfseek(Ft& f,
int offs,
int orig)
514 template<
class Ft>
long c4pftell(Ft& f)
520 MIKTEX_FATAL_CRT_ERROR(
"ftell");
525 template<
class Ft>
void c4pbufwrite(Ft& f,
const void* buf, std::size_t buf_size)
529 if (fwrite(buf, buf_size, 1, f) != 1)
531 MIKTEX_FATAL_CRT_ERROR(
"fwrite");
535 void c4pmemcpy(
void* pdst, std::size_t size,
const void* psrc, std::size_t count)
537 MIKTEX_ASSERT(size >= count);
538 MIKTEX_ASSERT_BUFFER(pdst, size);
540#if defined(_MSC_VER) && (_MSC_VER > 1400)
541 memcpy_s(pdst, size, psrc, count);
543 memcpy(pdst, psrc, count);
547 void c4pstrcpy(
char* dst, std::size_t size,
const char* src)
549 MiKTeX::Util::StringUtil::CopyCeeString(dst, size, src);
552 std::size_t c4pstrlen(
const char* lpsz)
554 MIKTEX_ASSERT_STRING(lpsz);
558 template<
class T>
bool c4pfopen(T& f,
const char* lpszName,
const char* lpszMode,
bool mustExist)
560 MIKTEX_ASSERT_STRING(lpszName);
561 MIKTEX_ASSERT_STRING(lpszMode);
563 (MiKTeX::Core::Utils::Equals(lpszMode,
"r")
564 || MiKTeX::Core::Utils::Equals(lpszMode,
"rb")
565 || MiKTeX::Core::Utils::Equals(lpszMode,
"w")
566 || MiKTeX::Core::Utils::Equals(lpszMode,
"wb"));
567 bool reading = (lpszMode[0] ==
'r');
568 bool text = (lpszMode[1] == 0);
570 MiKTeX::Util::PathName(lpszName),
577 template<
class T>
bool c4ptryfopen(T& f,
const char* lpszName,
const char* lpszMode)
579 return c4pfopen(f, lpszName, lpszMode,
false);
582 template<
class T>
void c4pfclose(T& f)
592 template<
class T> T* c4pptr(T& obj)
597 double c4p_abs(
double x)
607 double arctan(
double x)
612 template<
class T>
int chr(T i)
617 template<
class T> C4P_boolean eof(T& f)
626 template<
class T> C4P_boolean eoln(T& f)
631 template<
class T>
void get(T& f)
637 template<>
void get<BufferedFile<C4P_unsigned8>>(BufferedFile<C4P_unsigned8>&f)
640 if (
static_cast<int>(*f) == EOF)
642 MIKTEX_FATAL_CRT_ERROR(
"getc");
655 template<
class T> C4P_boolean odd(T i)
657 return (i & 1) != 0 ? true :
false;
660 template<
class T>
int ord(T x)
665 template<
class T> T pred(T x)
670 template<
class T>
void put(T& f)
675 template<
class T>
void reset(T& f)
680 template<
class T>
void rewrite(T& f)
690 template<
class T> T succ(T x)
695 template<
int handle>
void c4p_proc_entry()
699 template<
int handle>
void c4p_proc_exit()
703 const int c4pcur = SEEK_CUR;
704 const int c4pend = SEEK_END;
705 const int c4pset = SEEK_SET;
707 const char*
const c4prmode =
"r";
708 const char*
const c4pwmode =
"w";
709 const char*
const c4prbmode =
"rb";
710 const char*
const c4pwbmode =
"wb";
714 C4PTHISAPI(
void) WriteChar(
int ch, FILE* file);
717 std::unique_ptr<impl> pimpl;
720#define C4P_BEGIN_PROGRAM(programName, argc, argv) \
722 int c4p_retcode = 0; \
725 this->Initialize(programName, argc, argv);
727#define C4P_END_PROGRAM() \
732 c4p_retcode = retcode; \
734 return c4p_retcode; \
737#define c4pbegintryblock(n) \
741#define c4pendtryblock(n) \
744catch (const C4P::Exception##n&) \
748#define c4pthrow(n) throw C4P::Exception##n()
750#define C4P_FOR_BEGIN(var, startval, relop, lastval) \
752 int c4p_temp = (lastval); \
753 if ((var = (startval)) relop c4p_temp) \
758#define C4P_FOR_END(var, op) \
760 while (var op != c4p_temp); \
764C4PCEEAPI(C4P_integer) Round(
double r);
766#define C4P_PROC_ENTRY(handle) c4p_proc_entry<handle>();
767#define C4P_PROC_EXIT(handle) C4P_LABEL_PROC_EXIT: c4p_proc_exit<handle>();
769#define C4P_READ_BEGIN() {
770#define C4P_READLN_BEGIN() C4P_READ_BEGIN()
772#define C4P_READ_END(f) }
773#define C4P_READLN_END(f) f.DiscardLine(); }
775#define C4P_WRITE_BEGIN() {
776#define C4P_WRITELN_BEGIN() C4P_WRITE_BEGIN()
778#define C4P_WRITE_END(f) }
779#define C4P_WRITELN_END(f) putc('\n', f); }
781#define c4parrcpy(dst, src) c4pmemcpy(dst, sizeof(dst), src, sizeof(dst))
782#define c4pbreakloop() break
783#define c4pday GetDay()
784#define c4phour GetHour()
785#define c4pminute GetMinute()
786#define c4pmonth GetMonth()
787#define c4psecond GetSecond()
788#define c4pyear GetYear()
An instance of this class controls the run-time behaviour of a MiKTeX application.
Definition Application.h:37
Instances of this class can be used to store path names.
Definition PathName.h:64
FileAccess
File access options.
Definition File.h:72
@ Write
Write access.
Definition File.h:77
@ Read
Read access.
Definition File.h:75
FileMode
How to open a file.
Definition File.h:54
@ Create
The file will be created, if it doesn't already exist.
Definition File.h:61
@ Open
Open an existing file.
Definition File.h:65