1 #ifndef __IO_H__
2 #define __IO_H__
3
4
5 typedef struct file_descriptor {
6 FILE *f;
7 char *name;
8 #ifdef __VMS
9 void *fab;
10 #endif
11 int error;
12 short mode;
13 short state;
14 } file_descriptor;
15
16 typedef struct text_descriptor {
17 file_descriptor desc;
18 char record;
19 } text_descriptor;
20
21
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 extern boolean pio_ignore_error;
28
29 void pio_initialize(int argc, char const* argv[]);
30
31 void pio_rewrite_file(file_descriptor* fd,
32 size_t record_size,
33 const char* file_name, const char* options,
34 integer* error_code);
35
36 void pio_open_file(file_descriptor* fd,
37 size_t record_size,
38 const char* file_name,
39 const char* history,
40 integer* error_code);
41
42 void pio_reset_file(file_descriptor* fd,
43 size_t record_size,
44 const char* file_name, const char* options,
45 integer* error_code);
46
47 void pio_get_record(file_descriptor* fd, void* record, size_t record_size);
48
49
50 void pio_put_record(file_descriptor* fd, void* record, size_t record_size);
51
52
53 void pio_access_record(file_descriptor* fd, void* record, size_t record_size);
54
55
56 void pio_store_record(file_descriptor* fd, void* record, size_t record_size,
57 void* src);
58
59
60 void pio_read_record(file_descriptor* fd, void* record, size_t record_size,
61 void* dst);
62
63 void pio_write_record(file_descriptor* fd, void* record, size_t record_size,
64 void* src);
65
66 void pio_copy_record(file_descriptor* src_fd, void* src_record,
67 file_descriptor* dst_fd, void* dst_record,
68 size_t record_size);
69
70 boolean pio_check_end_of_file(file_descriptor *fd);
71
72 boolean pio_check_end_of_line(text_descriptor *td);
73
74 integer pio_iostatus(file_descriptor *fd);
75
76 boolean pio_ioerror(file_descriptor *fd);
77
78 void pio_file_ignore_error(file_descriptor* fd);
79
80 void pio_close_file(file_descriptor* fd);
81
82 void pio_seek_file(file_descriptor* fd, void* record, size_t record_size,
83 integer position);
84
85 void pio_rename_file(file_descriptor* fd, const char* new_name);
86
87 void pio_flush_file(file_descriptor* fd);
88
89 void pio_delete_file(file_descriptor* fd);
90
91 #ifdef __VMS
92 integer pio_get_file_version(file_descriptor* fd);
93 #endif
94
95
96 long pio_get_file_size(file_descriptor* fd, size_t record_size);
97
98 void pio_input_real(text_descriptor* td, double* val);
99
100 void pio_input_integer(text_descriptor* td, int* val);
101
102 void pio_input_unsigned(text_descriptor* td, unsigned* val);
103
104 void pio_input_long(text_descriptor* td, long* val);
105
106 void pio_input_ulong(text_descriptor* td, unsigned long* val);
107
108 void pio_input_char(text_descriptor* td, char* val);
109
110 int pio_input_string(text_descriptor* td, char* buf, size_t len, int padding);
111
112 void pio_input_newline(text_descriptor* td);
113
114
115 void pio_output_real(text_descriptor* td, double val, const int* width,
116 const int* prec);
117
118 void pio_output_integer(text_descriptor* td, int val,
119 const int* width);
120
121 void pio_output_unsigned(text_descriptor* td, unsigned val,
122 const int* width);
123
124 void pio_output_long(text_descriptor* td, long val,
125 const int* width);
126
127 void pio_output_ulong(text_descriptor* td, unsigned long val,
128 const int* width);
129
130 void pio_output_char(text_descriptor* td, char val, const int* width);
131
132 void pio_output_boolean(text_descriptor* td, boolean val,
133 const int* width);
134
135 void pio_output_string(text_descriptor* td, const char* buf, size_t len,
136 const int* width);
137
138 void pio_output_newline(text_descriptor* td);
139
140 void pio_output_end_of_page(text_descriptor* td);
141
142 typedef struct { int dummy; } new_line_marker;
143 extern new_line_marker NL;
144
145 #ifdef __cplusplus
146
147 }
148
149 //
150 // Some compilers report error when operator-> returns non-stuctural type
151 // (for exmaple "char*"). When SPLIT_FILE_CLASS option is defined, "file" class
152 // is divided into two parts, one of which is used as common base for
153 // "file of XXX" and "text", and second contains operator-> for access file
154 // record.
155 //
156 #ifdef SPLIT_FILE_CLASS
157 #define file file_template
158 #endif
159
160 template<class T>
161 class file {
162 public:
163 file_descriptor desc;
164 T record;
165
166 #ifdef TURBO_PASCAL
assign(file & f,const char * file_name)167 friend void assign(file& f, const char* file_name) {
168 f.desc.f = NULL;
169 f.desc.name = strdup(file_name);
170 }
BlockRead(file & f,void * buf,word size,word & read)171 friend void BlockRead(file& f, void* buf, word size, word& read) {
172 read = fread(buf, 1, size, f.desc.f);
173 }
BlockWrite(file & f,void const * buf,word size,word & written)174 friend void BlockWrite(file& f, void const* buf, word size, word& written){
175 written = fwrite(buf, 1, size, f.desc.f);
176 }
177 #endif
178
179
180
181 friend void open(file& f, const char* file_name, const char* history,
182 integer& error, int buffer = 0)
183 {
184 pio_open_file(&f.desc, sizeof(T), file_name, history, &error);
185 }
186
open(file & f,const char * file_name,const char * history)187 friend void open(file& f, const char* file_name, const char* history)
188 {
189 pio_open_file(&f.desc, sizeof(T), file_name, history, NULL);
190 }
191
192
rewrite(file & f,const char * file_name,const char * options,integer & error_code)193 friend void rewrite(file& f, const char* file_name,
194 const char* options,
195 integer& error_code)
196 {
197 pio_rewrite_file(&f.desc, sizeof(T), file_name, options, &error_code);
198 }
199
rewrite(file & f,const char * file_name,const char * options)200 friend void rewrite(file& f, const char* file_name, const char* options)
201 {
202 pio_rewrite_file(&f.desc, sizeof(T), file_name, options, NULL);
203 }
204
rewrite(file & f)205 friend void rewrite(file& f)
206 {
207 pio_rewrite_file(&f.desc, sizeof(T), NULL, NULL, NULL);
208 }
209
rewrite(file & f,const char * file_name)210 friend void rewrite(file& f, const char* file_name)
211 {
212 pio_rewrite_file(&f.desc, sizeof(T), file_name, NULL, NULL);
213 }
214
reset(file & f,const char * file_name,const char * options,integer & error_code)215 friend void reset(file& f, const char* file_name,
216 const char* options, integer& error_code)
217 {
218 pio_reset_file(&f.desc, sizeof(T), file_name, options, &error_code);
219 }
220
reset(file & f,const char * file_name,const char * options)221 friend void reset(file& f, const char* file_name, const char* options)
222 {
223 pio_reset_file(&f.desc, sizeof(T), file_name, options, NULL);
224 }
225
reset(file & f,const char * file_name)226 friend void reset(file& f, const char* file_name)
227 {
228 pio_reset_file(&f.desc, sizeof(T), file_name, NULL, NULL);
229 }
230
reset(file & f)231 friend void reset(file& f)
232 {
233 pio_reset_file(&f.desc, sizeof(T), NULL, NULL, NULL);
234 }
235
get(file & f)236 friend void get(file& f)
237 {
238 pio_get_record(&f.desc, (void*)&f.record, sizeof(T));
239 }
240
put(file & f)241 friend void put(file& f)
242 {
243 pio_put_record(&f.desc, (void*)&f.record, sizeof(T));
244 }
245
eof(file & f)246 friend boolean eof(file& f)
247 {
248 return pio_check_end_of_file(&f.desc);
249 }
250
iostatus(file & f)251 friend integer iostatus(file& f)
252 {
253 return pio_iostatus(&f.desc);
254 }
255
ioerror(file & f)256 friend boolean ioerror(file& f)
257 {
258 return pio_ioerror(&f.desc);
259 }
260
close(file & f)261 friend void close(file& f)
262 {
263 pio_close_file(&f.desc);
264 }
265
seek(file & f,integer position)266 friend void seek(file& f, integer position)
267 {
268 pio_seek_file(&f.desc, (void*)&f.record, sizeof(T), position);
269 }
270
rename(file & f,const char * new_name)271 friend void rename(file& f, const char* new_name)
272 {
273 pio_rename_file(&f.desc, new_name);
274 }
275
flush(file & f)276 friend void flush(file& f)
277 {
278 pio_flush_file(&f.desc);
279 }
280
Delete(file & f)281 friend void Delete(file& f)
282 {
283 pio_delete_file(&f.desc);
284 }
285
filesize(file & f)286 friend long filesize(file& f)
287 {
288 return pio_get_file_size(&f.desc, sizeof(T));
289 }
290
noioerror(file & f)291 friend void noioerror(file& f)
292 {
293 pio_file_ignore_error(&f.desc);
294 }
295
296 T& operator*()
297 {
298 pio_access_record(&desc, (void*)&record, sizeof(T));
299 return record;
300 }
301
302 #ifndef SPLIT_FILE_CLASS
303 T* operator->()
304 {
305 pio_access_record(&desc, (void*)&record, sizeof(T));
306 return &record;
307 }
308 #endif
309
store(file & f,T const & record)310 friend void store(file& f, T const& record)
311 {
312 pio_store_record(&f.desc, (void*)&f.record, sizeof(T), (void*)&record);
313 }
314
315 file& operator >> (T& x)
316 {
317 pio_read_record(&desc, (void*)&record, sizeof(T), (void*)&x);
318 return *this;
319 }
320 file& operator >> (file const& f)
321 {
322 pio_copy_record(&desc, (void*)&record,
323 (file_descriptor*)&f.desc, (void*)&f.record,
324 sizeof(T));
325 return *this;
326 }
327 file& operator << (T const& x)
328 {
329 pio_write_record(&desc, (void*)&record, sizeof(T), (void*)&x);
330 return *this;
331 }
332
file_is_opened(file const & f)333 friend boolean file_is_opened(file const& f)
334 {
335 return f.desc.f != NULL;
336 }
337
file()338 file() { desc.f = NULL; desc.name = NULL; }
~file()339 ~file() { pio_close_file(&desc); }
340 };
341
342 class text;
343
344 extern "C" text input, output;
345
346 class text : public file<char> {
347 public:
eof()348 friend boolean eof()
349 {
350 return pio_check_end_of_file(&input.desc);
351 }
eoln(text & t)352 friend boolean eoln(text& t)
353 {
354 return pio_check_end_of_line((text_descriptor*)&t);
355 }
eoln()356 friend boolean eoln()
357 {
358 return pio_check_end_of_line((text_descriptor*)&input);
359 }
360
361 text& operator >> (float& x)
362 {
363 double tmp;
364 pio_input_real((text_descriptor*)this, &tmp);
365 x = (float)tmp;
366 return *this;
367 }
368
369 text& operator >> (double& x)
370 {
371 pio_input_real((text_descriptor*)this, &x);
372 return *this;
373 }
374
375 text& operator >> (int& x)
376 {
377 pio_input_integer((text_descriptor*)this, &x);
378 return *this;
379 }
380
381 text& operator >> (unsigned& x)
382 {
383 pio_input_unsigned((text_descriptor*)this, &x);
384 return *this;
385 }
386
387 text& operator >> (long& x)
388 {
389 pio_input_long((text_descriptor*)this, &x);
390 return *this;
391 }
392
393 text& operator >> (unsigned long& x)
394 {
395 pio_input_ulong((text_descriptor*)this, &x);
396 return *this;
397 }
398
399 text& operator >> (short& x)
400 {
401 int tmp;
402 pio_input_integer((text_descriptor*)this, &tmp);
403 x = (short)tmp;
404 return *this;
405 }
406
407 text& operator >> (unsigned short& x)
408 {
409 int tmp;
410 pio_input_integer((text_descriptor*)this, &tmp);
411 x = (unsigned short)tmp;
412 return *this;
413 }
414
415 text& operator >> (unsigned char& x)
416 {
417 int tmp;
418 pio_input_integer((text_descriptor*)this, &tmp);
419 x = (unsigned char)tmp;
420 return *this;
421 }
422
423 text& operator >> (signed char& x)
424 {
425 int tmp;
426 pio_input_integer((text_descriptor*)this, &tmp);
427 x = (signed char)tmp;
428 return *this;
429 }
430
431 text& operator >> (char& x)
432 {
433 pio_input_char((text_descriptor*)this, &x);
434 return *this;
435 }
436
437 text& operator >> (new_line_marker&)
438 {
439 pio_input_newline((text_descriptor*)this);
440 return *this;
441 }
442
443 text& operator << (double x)
444 {
445 pio_output_real((text_descriptor*)this, x, NULL, NULL);
446 return *this;
447 }
448
449 text& operator << (long x)
450 {
451 pio_output_long((text_descriptor*)this, x, NULL);
452 return *this;
453 }
454
455 text& operator << (unsigned long x)
456 {
457 pio_output_ulong((text_descriptor*)this, x, NULL);
458 return *this;
459 }
460
461 text& operator << (int x)
462 {
463 pio_output_integer((text_descriptor*)this, x, NULL);
464 return *this;
465 }
466
467 text& operator << (unsigned x)
468 {
469 pio_output_unsigned((text_descriptor*)this, x, NULL);
470 return *this;
471 }
472
btos(boolean val)473 friend char* btos(boolean val) // convert boolean to ascii string
474 {
475 return (char*)(val ? " TRUE" : "FALSE");
476 }
477
478 text& operator << (char x)
479 {
480 pio_output_char((text_descriptor*)this, x, NULL);
481 return *this;
482 }
483
484 text& operator << (unsigned char x)
485 {
486 pio_output_char((text_descriptor*)this, x, NULL);
487 return *this;
488 }
489
490 text& operator << (const char* x)
491 {
492 pio_output_string((text_descriptor*)this, x, strlen(x), NULL);
493 return *this;
494 }
495
496 text& operator << (new_line_marker&)
497 {
498 pio_output_newline((text_descriptor*)this);
499 return *this;
500 }
501
page(text & t)502 friend void page(text& t)
503 {
504 pio_output_end_of_page((text_descriptor*)&t);
505 }
page()506 friend void page()
507 {
508 pio_output_end_of_page((text_descriptor*)&output);
509 }
510 };
511
512
513 #ifdef SPLIT_FILE_CLASS
514 #undef file
515 template<class T>
516 class file : public file_template<T> {
517 public:
518 T* operator->()
519 {
520 pio_access_record(&desc, (void*)&record, sizeof(T));
521 return &record;
522 }
523 };
524 #endif
525
526 #ifdef TURBO_PASCAL
527 typedef text untyped_file;
528 #endif
529
530 template<int size>
531 class format_string {
532 private:
533 char* buf;
534 int width;
535
536 public:
537 friend text& operator << (text& t, format_string const& fs) {
538 pio_output_string((text_descriptor*)&t, fs.buf, size, &fs.width);
539 return t;
540 }
format_string(const char * str_buf,int str_width)541 format_string(const char* str_buf, int str_width) {
542 buf = (char*)str_buf;
543 width = str_width;
544 }
545 };
546
547 #ifdef TURBO_PASCAL
548 class format_varying_string {
549 private:
550 char buf[256];
551 int size;
552 int width;
553
554 public:
555 friend text& operator << (text& t, format_varying_string const& fs) {
556 pio_output_string((text_descriptor*)&t, fs.buf, fs.size, &fs.width);
557 return t;
558 }
format_varying_string(const char * str_buf,int str_size,int str_width)559 format_varying_string(const char* str_buf, int str_size, int str_width) {
560 memcpy(buf, str_buf, str_size);
561 size = str_size;
562 width = str_width;
563 }
564 };
565 #endif
566
567 class format_real {
568 private:
569 real val;
570 int width;
571
572 public:
573 friend text& operator << (text &t, format_real const& fr) {
574 pio_output_real((text_descriptor*)&t, fr.val, &fr.width, NULL);
575 return t;
576 }
format_real(real real_val,int real_width)577 format_real(real real_val, int real_width) {
578 val = real_val;
579 width = real_width;
580 }
581 };
582
format(real val,int width)583 inline format_real format(real val, int width) {
584 return format_real(val, width);
585 }
586
587
588 class format_real_wp {
589 private:
590 real val;
591 int width;
592 int prec;
593
594 public:
595 friend text& operator << (text &t, format_real_wp const& fr) {
596 pio_output_real((text_descriptor*)&t, fr.val, &fr.width, &fr.prec);
597 return t;
598 }
format_real_wp(real real_val,int real_width,int real_prec)599 format_real_wp(real real_val, int real_width, int real_prec) {
600 val = real_val;
601 prec = real_prec;
602 width = real_width;
603 }
604 };
605
format(real val,int width,int prec)606 inline format_real_wp format(real val, int width, int prec) {
607 return format_real_wp(val, width, prec);
608 }
609
610 class format_integer {
611 private:
612 int val;
613 int width;
614
615 public:
616 friend text& operator << (text &t, format_integer const& fi) {
617 pio_output_integer((text_descriptor*)&t, fi.val, &fi.width);
618 return t;
619 }
format_integer(int int_val,int int_width)620 format_integer(int int_val, int int_width) {
621 val = int_val;
622 width = int_width;
623 }
624 };
625
format(int val,int width)626 inline format_integer format(int val, int width) {
627 return format_integer(val, width);
628 }
629
630
631 class format_unsigned {
632 private:
633 unsigned val;
634 int width;
635
636 public:
637 friend text& operator << (text &t, format_unsigned const& fi) {
638 pio_output_unsigned((text_descriptor*)&t, fi.val, &fi.width);
639 return t;
640 }
format_unsigned(unsigned unsigned_val,int unsigned_width)641 format_unsigned(unsigned unsigned_val, int unsigned_width) {
642 val = unsigned_val;
643 width = unsigned_width;
644 }
645 };
646
format(unsigned val,int width)647 inline format_unsigned format(unsigned val, int width) {
648 return format_unsigned(val, width);
649 }
650
651
652 class format_long {
653 private:
654 long val;
655 int width;
656
657 public:
658 friend text& operator << (text &t, format_long const& fi) {
659 pio_output_long((text_descriptor*)&t, fi.val, &fi.width);
660 return t;
661 }
format_long(long long_val,int long_width)662 format_long(long long_val, int long_width) {
663 val = long_val;
664 width = long_width;
665 }
666 };
667
format(long val,int width)668 inline format_long format(long val, int width) {
669 return format_long(val, width);
670 }
671
672
673 class format_ulong {
674 private:
675 unsigned long val;
676 int width;
677
678 public:
679 friend text& operator << (text &t, format_ulong const& fi) {
680 pio_output_ulong((text_descriptor*)&t, fi.val, &fi.width);
681 return t;
682 }
format_ulong(unsigned long ulong_val,int ulong_width)683 format_ulong(unsigned long ulong_val, int ulong_width) {
684 val = ulong_val;
685 width = ulong_width;
686 }
687 };
688
format(unsigned long val,int width)689 inline format_ulong format(unsigned long val, int width) {
690 return format_ulong(val, width);
691 }
692
693
694
695 class format_lpsz {
696 private:
697 const char* val;
698 int width;
699
700 public:
701 friend text& operator << (text &t, format_lpsz const& fs) {
702 pio_output_string((text_descriptor*)&t, fs.val, strlen(fs.val),
703 &fs.width);
704 return t;
705 }
format_lpsz(const char * lpsz_val,int lpsz_width)706 format_lpsz(const char* lpsz_val, int lpsz_width) {
707 val = lpsz_val;
708 width = lpsz_width;
709 }
710 };
711
format(const char * val,int width)712 inline format_lpsz format(const char* val, int width) {
713 return format_lpsz(val, width);
714 }
715
716
717 class format_char {
718 private:
719 char val;
720 int width;
721
722 public:
723 friend text& operator << (text &t, format_char const& fc) {
724 pio_output_char((text_descriptor*)&t, fc.val, &fc.width);
725 return t;
726 }
format_char(char char_val,int char_width)727 format_char(char char_val, int char_width) {
728 val = char_val;
729 width = char_width;
730 }
731 };
732
format(char val,int width)733 inline format_char format(char val, int width) {
734 return format_char(val, width);
735 }
736
737
738 #else
739
740 #define file(type) struct { \
741 file_descriptor desc; \
742 type record; \
743 }
744
745 typedef text_descriptor text;
746
747 extern text input, output;
748
749 #define VOID_FILE {{0}}
750
751 #define rewrite(file_variable, file_name, options, error_code) \
752 pio_rewrite_file(&(file_variable).desc, \
753 sizeof((file_variable).record), \
754 file_name, options, error_code)
755
756 #define reset(file_variable, file_name, options, error_code) \
757 pio_reset_file(&(file_variable).desc, \
758 sizeof((file_variable).record), \
759 file_name, options, error_code)
760
761 #define get(file_variable) \
762 pio_get_record(&(file_variable).desc, (void*)&(file_variable).record, \
763 sizeof((file_variable).record))
764
765 #define put(file_variable) \
766 pio_put_record(&(file_variable).desc, (void*)&(file_variable).record, \
767 sizeof((file_variable).record))
768
769 #define sread(file_variable, value) \
770 pio_read_record(&(file_variable).desc, (void*)&(file_variable).record,\
771 sizeof((file_variable).record), (void*)&(value))
772
773 #define scopy(src_file, dst_file) \
774 pio_copy_record(&(src_file).desc, (void*)&(src_file).record,\
775 &(dst_file).desc, (void*)&(dst_file).record,\
776 sizeof((src_file).record))
777
778 #define swrite(file_variable, value) \
779 pio_write_record(&(file_variable).desc,(void*)&(file_variable).record,\
780 sizeof((file_variable).record), (void*)&(value))
781
782 #define currec(file_variable) \
783 (pio_access_record(&(file_variable).desc, \
784 (void*)&(file_variable).record, \
785 sizeof((file_variable).record)), \
786 &(file_variable).record)
787
788 #define store(file_variable, value) \
789 pio_store_record(&(file_variable).desc, \
790 (void*)&(file_variable).record, \
791 sizeof((file_variable).record), (void*)&(value))
792
793 #define eof(file_variable) \
794 pio_check_end_of_file(&(file_variable).desc)
795
796 #define iostatus(file_variable) \
797 pio_iostatus(&(file_variable).desc)
798
799 #define ioerror(file_variable) \
800 pio_ioerror(&(file_variable).desc)
801
802
803 #define close(file_variable) \
804 pio_close_file(&(file_variable).desc)
805
806 #define seek(file_variable, position) \
807 pio_seek_file(&(file_variable).desc, (void*)&(file_variable).record, \
808 sizeof((file_variable).record), position)
809
810 #define rename(file_variable, new_name) \
811 pio_rename_file(&(file_variable).desc, new_name)
812
813 #define flush(file_variable) \
814 pio_flush_file(&(file_variable).desc)
815
816 #define Delete(file_variable) \
817 pio_delete_file(&(file_variable).desc)
818
819 #define noioerror(file_variable) \
820 pio_file_ignore_error(&(file_variable).desc)
821
822 #ifdef __VMS
823 #define get_file_version(file_variable) \
824 pio_get_file_version(&(file_variable).desc)
825 #endif
826
827
828 #define file_is_opened(file_variable) ((file_variable).desc.f != NULL)
829
830
831 #define page(text_variable) \
832 pio_output_end_of_page(&text_variable)
833
834 #define eoln(text_variable) \
835 pio_check_end_of_line(&text_variable)
836
837
838 void tread(text* text_file, char* format_string, ...);
839
840 void twrite(text* text_file, char* format_string, ...);
841
842 void cread(char* format_string, ...);
843
844 void cwrite(char* format_string, ...);
845
846 #endif
847
848 #ifdef TURBO_PASCAL
849 extern "C" integer ioresult;
850 #define ioResult ioresult
851 #endif
852
853 /*
854 * Codes returned by Sun Pascal open()
855 */
856 enum open_file_errors {
857 file_successfully_opened = 0,
858 file_not_specified = 1,
859 unable_to_open_file = 2,
860 invalid_history = 3,
861 file_already_exists = 4
862 };
863
864
865 #endif
866
867
868