MiKTeX 26.5-next
A scalable TeX distribution
Loading...
Searching...
No Matches
C4P.h
Go to the documentation of this file.
1
13
14#pragma once
15
16#include <miktex/C4P/config.h>
17
18#include <cctype>
19#include <climits>
20#include <cmath>
21#include <csignal>
22#include <cstddef>
23#include <cstdio>
24#include <cstdlib>
25#include <cstring>
26
27#include <exception>
28#include <memory>
29#include <string>
30#include <vector>
31
32#include <miktex/App/Application>
33
34#include <miktex/Core/File>
35#include <miktex/Core/IntegerTypes>
36#include <miktex/Core/Session>
37
38#include <miktex/Util/StringUtil>
40
47C4P_BEGIN_NAMESPACE;
48
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;
57
58typedef int C4P_integer;
59typedef MIKTEX_INT64 C4P_longinteger;
60
61#if defined(C4P_REAL_IS_DOUBLE)
62typedef double C4P_real;
63#else
64typedef float C4P_real;
65#endif
66
67typedef double C4P_longreal;
68
69// assert (sizeof(bool) == 1)
70typedef bool C4P_boolean;
71
73{
74
75public:
76
77 C4PTHISAPI(bool) Open(const MiKTeX::Util::PathName& path, MiKTeX::Core::FileMode mode, MiKTeX::Core::FileAccess access, bool text, bool mustExist);
78
79 void AssertValid() const
80 {
81 MIKTEX_ASSERT(file != nullptr);
82 }
83
84 void Close()
85 {
86 AssertValid();
87 FILE* file = this->file;
88 this->file = nullptr;
89 if ((flags & NotOwner) != 0)
90 {
91 std::shared_ptr<MiKTeX::Core::Session> session = MIKTEX_SESSION();
92 session->CloseFile(file);
93 }
94 }
95
96 void Attach(FILE* file, bool takeOwnership)
97 {
98 flags = 0;
99 if (!takeOwnership)
100 {
101 flags |= NotOwner;
102 }
103 this->file = file;
104 }
105
106 operator FILE*()
107 {
108 return file;
109 }
110
111 FILE*& fileref()
112 {
113 flags = 0;
114 return file;
115 }
116
117 FILE* operator->()
118 {
119 return file;
120 }
121
122protected:
123
124 FILE* file = nullptr;
125 enum { NotOwner = 0x00000001 };
126 unsigned flags = 0;
128};
129
130template<class T> struct BufferedFile :
131 public FileRoot
132{
133
134public:
135
136 typedef T ElementType;
137
138 void PascalFileIO(bool turnOn)
139 {
140 if (turnOn)
141 {
142 flags |= Buffered;
143 }
144 else
145 {
146 flags &= ~Buffered;
147 }
148 }
149
150 bool IsPascalFileIO() const
151 {
152 return (flags & Buffered) != 0;
153 }
154
155 const ElementType& bufref() const
156 {
157 MIKTEX_EXPECT(IsPascalFileIO());
158 return currentElement;
159 }
160
161 ElementType& bufref()
162 {
163 PascalFileIO(true);
164 return currentElement;
165 }
166
167 const ElementType& operator*() const
168 {
169 return bufref();
170 }
171
172 ElementType& operator*()
173 {
174 return bufref();
175 }
176
177 bool Eof()
178 {
179 if (feof(file) != 0)
180 {
181 return true;
182 }
183
184 if (IsPascalFileIO())
185 {
186 return false;
187 }
188
189 int lookAhead = getc(file);
190
191 if (lookAhead == EOF)
192 {
193 if (ferror(file) != 0)
194 {
195 MIKTEX_FATAL_CRT_ERROR_2("getc", "path", path.ToString());
196 }
197 return true;
198 }
199
200 if (ungetc(lookAhead, file) != lookAhead)
201 {
202 MIKTEX_FATAL_CRT_ERROR_2("ungetc", "path", path.ToString());
203 }
204
205 return false;
206 }
207
208 bool Eoln()
209 {
210 if (feof(file) != 0)
211 {
212 return true;
213 }
214
215 if (IsPascalFileIO())
216 {
217 return currentElement == '\r' || currentElement == '\n';
218 }
219
220 int lookAhead = getc(file);
221
222 if (lookAhead == EOF)
223 {
224 if (ferror(file) != 0)
225 {
226 MIKTEX_FATAL_CRT_ERROR_2("getc", "path", path.ToString());
227 }
228 return true;
229 }
230
231 if (ungetc(lookAhead, file) != lookAhead)
232 {
233 MIKTEX_FATAL_CRT_ERROR_2("ungetc", "path", path.ToString());
234 }
235
236 return lookAhead == '\r' || lookAhead == '\n';
237 }
238
239 void Read(ElementType* buf, std::size_t n)
240 {
241 std::size_t read = ReadInternal(buf, n);
242 if (read != n)
243 {
244 MIKTEX_FATAL_ERROR_2(MIKTEXTEXT("Read operation failed."), "path", path.ToString(), "read", std::to_string(read), "n", std::to_string(n));
245 }
246 if (IsPascalFileIO())
247 {
248 currentElement = buf[n - 1];
249 }
250 }
251
252 void Read()
253 {
254 PascalFileIO(true);
255 ReadInternal(&currentElement, 1);
256 }
257
258 void Reset()
259 {
260 AssertValid();
261 rewind(*this);
262 Read();
263 }
264
265 void Rewrite()
266 {
267 AssertValid();
268 rewind(*this);
269 }
270
271 void Write()
272 {
273 AssertValid();
274 MIKTEX_ASSERT(IsPascalFileIO());
275 if (fwrite(&currentElement, sizeof(ElementType), 1, *this) != 1 || ferror(*this) != 0)
276 {
277 MIKTEX_FATAL_CRT_ERROR_2("fwrite", "path", path.ToString());
278 }
279 }
280
281 void Seek(long offset, int origin)
282 {
283 AssertValid();
284 if (fseek(*this, offset, origin) != 0)
285 {
286 MIKTEX_FATAL_CRT_ERROR_2("fseek", "path", path.ToString(), "offset", std::to_string(offset), "origin", std::to_string(origin));
287 }
288 if (IsPascalFileIO() && !(origin == SEEK_END && offset == 0))
289 {
290 Read();
291 }
292 }
293
294protected:
295
296 enum { Buffered = 0x00010000 };
297
298 ElementType currentElement;
299
300 std::size_t ReadInternal(ElementType* buf, std::size_t n)
301 {
302 AssertValid();
303 MIKTEX_ASSERT_BUFFER(buf, n);
304 if (feof(*this) != 0)
305 {
306 MIKTEX_FATAL_ERROR_2(MIKTEXTEXT("Read operation failed: end of file reached"), "path", path.ToString(), "n", std::to_string(n));
307 }
308 size_t read = fread(buf, sizeof(ElementType), n, *this);
309 if (ferror(*this) != 0)
310 {
311 MIKTEX_FATAL_CRT_ERROR_2("ferror", "path", path.ToString());
312 }
313 if (read != n)
314 {
315 MIKTEX_EXPECT(feof(*this));
316 }
317 return read;
318 }
319
320
321};
322
323#define C4P_FILE_STRUCT(Bt) C4P::BufferedFile<Bt>
324
325struct C4P_text :
326 BufferedFile<char>
327{
328public:
329 C4PTHISAPI(C4P_real) GetReal();
330 C4PTHISAPI(bool) IsTerminal();
331 C4PTHISAPI(char) GetChar();
332 C4PTHISAPI(int) GetInteger();
333 C4PTHISAPI(void) DiscardLine();
334};
335
336#define c4pargc GetArgC()
337#define c4pargv GetArgV()
338
339#define c4ppline GetCmdLine()
340#define c4pplen strlen(GetCmdLine())
341
342#define input (*(GetStdFilePtr(0)))
343#define output (*(GetStdFilePtr(1)))
344#define c4perroroutput (*(GetStdFilePtr(2)))
345
346class C4PTYPEAPI(ProgramBase)
347{
348
349public:
350
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();
356 C4PTHISAPI(void) SetParent(MiKTeX::App::Application* parent);
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;
363
364protected:
365
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[]);
376
377 template<class Ft> void c4p_write_f(Ft&, Ft&)
378 {
379 }
380
381 template<class Vt, class Ft> void c4p_write_v(Vt v, Ft& f)
382 {
383 f.AssertValid();
384 *f = v;
385 put(f);
386 }
387
388 template<class Vt, class Ft> void c4p_write_c(Vt v, Ft& f)
389 {
390 f.AssertValid();
391 WriteChar(v, f);
392 }
393
394 template<class Vt, class Ft> void c4p_write_c1(Vt v, Ft& f)
395 {
396 return c4p_write_c(v, f);
397 }
398
399 template<class Vt, class Ft> void c4p_write_i(Vt v, Ft& f)
400 {
401 f.AssertValid();
402 if (fprintf(f, "%ld", static_cast<long>(v)) < 0)
403 {
404 MIKTEX_FATAL_CRT_ERROR("fprintf");
405 }
406 }
407
408 template<class Vt, class Ft> void c4p_write_i1(Vt v, int w1, Ft& f)
409 {
410 f.AssertValid();
411 if (fprintf(f, "%*ld", static_cast<int>(w1), static_cast<long>(v)) < 0)
412 {
413 MIKTEX_FATAL_CRT_ERROR("fprintf");
414 }
415 }
416
417 template<class Vt, class Ft> void c4p_write_i2(Vt v, int w1, int w2, Ft& f)
418 {
419 f.AssertValid();
420 if (fprintf(f, "%*.*ld", static_cast<int>(w1), static_cast<int>(w2), static_cast<long>(v)) < 0)
421 {
422 MIKTEX_FATAL_CRT_ERROR("fprintf");
423 }
424 }
425
426 template<class Vt, class Ft> void c4p_write_r(Vt v, Ft& f)
427 {
428 f.AssertValid();
429 if (fprintf(f, "%f", static_cast<float>(v)) < 0)
430 {
431 MIKTEX_FATAL_CRT_ERROR("fprintf");
432 }
433 }
434
435 template<class Vt, class Ft> void c4p_write_r2(Vt v, int w1, int w2, Ft& f)
436 {
437 f.AssertValid();
438 if (fprintf(f, "%*.*f", static_cast<int>(w1), static_cast<int>(w2), static_cast<float>(v)) < 0)
439 {
440 MIKTEX_FATAL_CRT_ERROR("fprintf");
441 }
442 }
443
444 template <class Vt, class Ft> void c4p_write_s(Vt v, Ft& f)
445 {
446 f.AssertValid();
447 if (fputs(reinterpret_cast<const char*>(v), f) == EOF)
448 {
449 MIKTEX_FATAL_CRT_ERROR("fputs");
450 }
451 }
452
453 template<class Ft> void c4p_read_f(Ft&, Ft&)
454 {
455 }
456
457 template<class Vt, class Ft> void c4p_read_v(Vt& v, Ft& f)
458 {
459 f.AssertValid();
460 v = *f;
461 get(f);
462 }
463
464 template<class Vt, class Ft> void c4p_read_c(Vt& v, Ft& f)
465 {
466 f.AssertValid();
467 v = f.GetChar();
468 }
469
470 template<class Vt, class Ft> void c4p_read_i(Vt& v, Ft& f)
471 {
472 f.AssertValid();
473 v = f.GetInteger();
474 }
475
476 template<class Vt, class Ft> void c4p_read_r(Vt& v, Ft& f)
477 {
478 f.AssertValid();
479 v = f.GetReal();
480 }
481
482 const C4P_integer maxint = INT_MAX;
483
484 void c4p_readln()
485 {
486 input.AssertValid();
487 input.DiscardLine();
488 }
489
490 void c4p_writeln()
491 {
492 output.AssertValid();
493 if (putc('\n', output) == EOF)
494 {
495 MIKTEX_FATAL_CRT_ERROR("putc");
496 }
497 }
498
499 template<class T> void c4p_break(T& f)
500 {
501 f.AssertValid();
502 if (fflush(f) == EOF)
503 {
504 MIKTEX_FATAL_CRT_ERROR("flush");
505 }
506 }
507
508 template<class Ft> void c4pfseek(Ft& f, int offs, int orig)
509 {
510 f.AssertValid();
511 f.Seek(offs, orig);
512 }
513
514 template<class Ft> long c4pftell(Ft& f)
515 {
516 f.AssertValid();
517 long n = ftell(f);
518 if (n < 0)
519 {
520 MIKTEX_FATAL_CRT_ERROR("ftell");
521 }
522 return n;
523 }
524
525 template<class Ft> void c4pbufwrite(Ft& f, const void* buf, std::size_t buf_size)
526 {
527 f.AssertValid();
528 //MIKTEX_ASSERT_BUFFER (buf, buf_size);
529 if (fwrite(buf, buf_size, 1, f) != 1)
530 {
531 MIKTEX_FATAL_CRT_ERROR("fwrite");
532 }
533 }
534
535 void c4pmemcpy(void* pdst, std::size_t size, const void* psrc, std::size_t count)
536 {
537 MIKTEX_ASSERT(size >= count);
538 MIKTEX_ASSERT_BUFFER(pdst, size);
539 //MIKTEX_ASSERT_BUFFER (psrc, count);
540#if defined(_MSC_VER) && (_MSC_VER > 1400)
541 memcpy_s(pdst, size, psrc, count);
542#else
543 memcpy(pdst, psrc, count);
544#endif
545 }
546
547 void c4pstrcpy(char* dst, std::size_t size, const char* src)
548 {
549 MiKTeX::Util::StringUtil::CopyCeeString(dst, size, src);
550 }
551
552 std::size_t c4pstrlen(const char* lpsz)
553 {
554 MIKTEX_ASSERT_STRING(lpsz);
555 return strlen(lpsz);
556 }
557
558 template<class T> bool c4pfopen(T& f, const char* lpszName, const char* lpszMode, bool mustExist)
559 {
560 MIKTEX_ASSERT_STRING(lpszName);
561 MIKTEX_ASSERT_STRING(lpszMode);
562 MIKTEX_ASSERT
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);
569 return f.Open(
570 MiKTeX::Util::PathName(lpszName),
573 text,
574 mustExist);
575 }
576
577 template<class T> bool c4ptryfopen(T& f, const char* lpszName, const char* lpszMode)
578 {
579 return c4pfopen(f, lpszName, lpszMode, false);
580 }
581
582 template<class T> void c4pfclose(T& f)
583 {
584 f.Close();
585 }
586
587 void c4pexit(int n)
588 {
589 throw n;
590 }
591
592 template<class T> T* c4pptr(T& obj)
593 {
594 return &obj;
595 };
596
597 double c4p_abs(double x)
598 {
599 return ::fabs(x);
600 }
601
602 int c4p_abs(int x)
603 {
604 return ::abs(x);
605 }
606
607 double arctan(double x)
608 {
609 return atan(x);
610 }
611
612 template<class T> int chr(T i)
613 {
614 return i;
615 }
616
617 template<class T> C4P_boolean eof(T& f)
618 {
619#if 0
620 return feof(f) != 0;
621#else
622 return f.Eof();
623#endif
624 }
625
626 template<class T> C4P_boolean eoln(T& f)
627 {
628 return f.Eoln();
629 };
630
631 template<class T> void get(T& f)
632 {
633 f.Read();
634 }
635
636#if 0 // optimization?
637 template<> void get<BufferedFile<C4P_unsigned8>>(BufferedFile<C4P_unsigned8>&f)
638 {
639 *f = getc(f);
640 if (static_cast<int>(*f) == EOF)
641 {
642 MIKTEX_FATAL_CRT_ERROR("getc");
643 }
644 }
645#endif
646
647 double ln(double x)
648 {
649 return log(x);
650 }
651
652#if defined(odd)
653# undef odd
654#endif
655 template<class T> C4P_boolean odd(T i)
656 {
657 return (i & 1) != 0 ? true : false;
658 }
659
660 template<class T> int ord(T x)
661 {
662 return x;
663 }
664
665 template<class T> T pred(T x)
666 {
667 return x - 1;
668 }
669
670 template<class T> void put(T& f)
671 {
672 f.Write();
673 }
674
675 template<class T> void reset(T& f)
676 {
677 f.Reset();
678 }
679
680 template<class T> void rewrite(T& f)
681 {
682 f.Rewrite();
683 }
684
685 double sqr(double x)
686 {
687 return sqrt(x);
688 }
689
690 template<class T> T succ(T x)
691 {
692 return x + 1;
693 }
694
695 template<int handle> void c4p_proc_entry()
696 {
697 }
698
699 template<int handle> void c4p_proc_exit()
700 {
701 }
702
703 const int c4pcur = SEEK_CUR;
704 const int c4pend = SEEK_END;
705 const int c4pset = SEEK_SET;
706
707 const char* const c4prmode = "r";
708 const char* const c4pwmode = "w";
709 const char* const c4prbmode = "rb";
710 const char* const c4pwbmode = "wb";
711
712private:
713
714 C4PTHISAPI(void) WriteChar(int ch, FILE* file);
715
716 class impl;
717 std::unique_ptr<impl> pimpl;
718};
719
720#define C4P_BEGIN_PROGRAM(programName, argc, argv) \
721{ \
722 int c4p_retcode = 0; \
723 try \
724 { \
725 this->Initialize(programName, argc, argv);
726
727#define C4P_END_PROGRAM() \
728 this->Finish(); \
729 } \
730 catch(int retcode) \
731 { \
732 c4p_retcode = retcode; \
733 } \
734 return c4p_retcode; \
735}
736
737#define c4pbegintryblock(n) \
738try \
739{
740
741#define c4pendtryblock(n) \
742 ; \
743} \
744catch (const C4P::Exception##n&) \
745{ \
746}
747
748#define c4pthrow(n) throw C4P::Exception##n()
749
750#define C4P_FOR_BEGIN(var, startval, relop, lastval) \
751{ \
752 int c4p_temp = (lastval); \
753 if ((var = (startval)) relop c4p_temp) \
754 { \
755 do \
756 {
757
758#define C4P_FOR_END(var, op) \
759 } \
760 while (var op != c4p_temp); \
761 } \
762}
763
764C4PCEEAPI(C4P_integer) Round(double r);
765
766#define C4P_PROC_ENTRY(handle) c4p_proc_entry<handle>();
767#define C4P_PROC_EXIT(handle) C4P_LABEL_PROC_EXIT: c4p_proc_exit<handle>();
768
769#define C4P_READ_BEGIN() {
770#define C4P_READLN_BEGIN() C4P_READ_BEGIN()
771
772#define C4P_READ_END(f) }
773#define C4P_READLN_END(f) f.DiscardLine(); }
774
775#define C4P_WRITE_BEGIN() {
776#define C4P_WRITELN_BEGIN() C4P_WRITE_BEGIN()
777
778#define C4P_WRITE_END(f) }
779#define C4P_WRITELN_END(f) putc('\n', f); }
780
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()
789
790C4P_END_NAMESPACE;
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
Inline functions.
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
Definition C4P.h:132
Definition C4P.h:327
Definition C4P.h:73