00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <basix/posix_port.hpp>
00014 #include <basix/system.hpp>
00015 #include <fcntl.h>
00016 #include <unistd.h>
00017 #include <sys/types.h>
00018
00019 #if defined(__MINGW__) || defined(__MINGW32__)
00020 # include <stdio.h>
00021 # include <share.h>
00022 #endif
00023
00025
00026 namespace mmx {
00027
00028
00029
00030
00031
00032 static void
00033 get_lock (FILE* f, int kind) {
00034 #if !(defined(__MINGW__) || defined(__MINGW32__))
00035 struct flock fl;
00036 int fd= fileno (f);
00037 fl.l_type = kind == 2? F_RDLCK: F_WRLCK;
00038 fl.l_whence = SEEK_SET;
00039 fl.l_start = 0;
00040 fl.l_len = 0;
00041 fl.l_pid = getpid ();
00042 fcntl (fd, F_SETLKW, &fl);
00043
00044 #endif
00045 }
00046
00047 static void
00048 release_lock (FILE* f) {
00049 #if !(defined(__MINGW__) || defined(__MINGW32__))
00050 struct flock fl;
00051 int fd= fileno (f);
00052 fl.l_type = F_UNLCK;
00053 fl.l_whence = SEEK_SET;
00054 fl.l_start = 0;
00055 fl.l_len = 0;
00056 fl.l_pid = getpid ();
00057 fcntl (fd, F_SETLK, &fl);
00058
00059 #endif
00060 }
00061
00062
00063
00064
00065
00066 class file_port_rep: public posix_port_rep {
00067 FILE* f;
00068 bool cf;
00069 bool lock;
00070 string name;
00071 int next;
00072
00073 public:
00074 syntactic expression () const {
00075 if (this->kind == 1) return syn ("output_file_port", syntactic (name));
00076 if (this->kind == 2) return syn ("input_file_port", syntactic (name));
00077 return syn ("input_output_file_port", syntactic (name));
00078 }
00079
00080 bool busy () {
00081 if (this->kind == 2) return can_read () > 0;
00082 return true;
00083 }
00084 nat can_write () {
00085 if (this->kind == 2) return 0;
00086 return (nat) (-1);
00087 }
00088 nat can_read () {
00089 if (next != -1) return 1;
00090 if (this->kind == 1 || feof (f) != 0) return 0;
00091 next= fgetc (f);
00092 if (next != -1) return 1;
00093 return 0;
00094 }
00095
00096 void write (const char* s, nat n) {
00097 for (nat i=0; i<n; i++) fputc (s[i], f); }
00098 void read (char* s, nat n) {
00099 if (next != -1 && n > 0) { s[0]= next; s++; n--; next= -1; }
00100 for (nat i=0; i<n; i++) s[i]= fgetc (f); }
00101
00102 void flush () { fflush (f); }
00103
00104 public:
00105 inline file_port_rep (int kind, FILE* f2, bool cf2, bool lock2,
00106 const string& name2):
00107 posix_port_rep (kind, fileno (f2)),
00108 f (f2), cf (cf2), lock (lock2), name (name2), next (-1) {
00109 if (lock) get_lock (f, this->kind); }
00110 inline ~file_port_rep () {
00111 if (lock) release_lock (f);
00112 if (cf) fclose (f); }
00113 };
00114
00115 static port
00116 output_file_port (FILE* f, bool close_flag, bool lock, const string& name) {
00117 return (port_rep*) new file_port_rep (1, f, close_flag, lock, name);
00118 }
00119
00120 static port
00121 input_file_port (FILE* f, bool close_flag, bool lock, const string& name) {
00122 return (port_rep*) new file_port_rep (2, f, close_flag, lock, name);
00123 }
00124
00125 static port
00126 input_output_file_port (FILE* f, bool cf, bool lock, const string& name) {
00127 return (port_rep*) new file_port_rep (3, f, cf, lock, name);
00128 }
00129
00130
00131
00132
00133
00134 table<int,int> out_count (0);
00135 table<int,int> in_count (0);
00136
00137 port mmin = input_file_port (stdin , false, false, "mmin");
00138 port mmout= formatting_port (output_file_port (stdout, false, false, "mmout"));
00139 port mmerr= formatting_port (output_file_port (stderr, false, false, "mmerr"));
00140
00141 port
00142 output_file_port (const string& name) {
00143 string name_s= decode_name (name);
00144 char* temp= as_charp (name_s);
00145 #if defined(__MINGW__) || defined(__MINGW32__)
00146 FILE* f= _fsopen (temp, "w", _SH_DENYRW);
00147 #else
00148 FILE* f= fopen (temp, "w");
00149 #endif
00150 free_charp (temp);
00151 if (f == NULL) return error_port ("file '" * name * "' not writable");
00152 return output_file_port (f, true, true, name);
00153 }
00154
00155 port
00156 input_file_port (const string& name) {
00157 string name_s= decode_name (name);
00158 char* temp= as_charp (name_s);
00159 #if defined(__MINGW__) || defined(__MINGW32__)
00160 FILE* f= _fsopen (temp, "r", _SH_DENYWR);
00161 #else
00162 FILE* f= fopen (temp, "r");
00163 #endif
00164 free_charp (temp);
00165 if (f == NULL) return error_port ("file '" * name * "' not found");
00166 return input_file_port (f, true, true, name);
00167 }
00168
00169 port
00170 input_output_file_port (const string& name) {
00171 string name_s= decode_name (name);
00172 char* temp= as_charp (name_s);
00173 #if defined(__MINGW__) || defined(__MINGW32__)
00174 FILE* f= _fsopen (temp, "w+", _SH_DENYRW);
00175 #else
00176 FILE* f= fopen (temp, "w+");
00177 #endif
00178 free_charp (temp);
00179 if (f == NULL) return error_port ("file '" * name * "' did not open");
00180 return input_output_file_port (f, true, true, name);
00181 }
00182
00183 }