/[cebix]/Frodo4/Src/1541fs.cpp
ViewVC logotype

Diff of /Frodo4/Src/1541fs.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by cebix, Wed Jul 9 13:54:22 2003 UTC revision 1.4 by cebix, Sun Jan 11 00:09:51 2004 UTC
# Line 47  Line 47 
47  #endif  #endif
48    
49    
 // Access modes  
 enum {  
         FMODE_READ, FMODE_WRITE, FMODE_APPEND  
 };  
   
 // File types  
 enum {  
         FTYPE_PRG, FTYPE_SEQ  
 };  
   
50  // Prototypes  // Prototypes
51  static bool match(char *p, char *n);  static bool match(const char *p, const char *n);
52    
53    
54  /*  /*
# Line 127  bool FSDrive::change_dir(char *dirpath) Line 117  bool FSDrive::change_dir(char *dirpath)
117   *  Open channel   *  Open channel
118   */   */
119    
120  uint8 FSDrive::Open(int channel, char *filename)  uint8 FSDrive::Open(int channel, const uint8 *name, int name_len)
121  {  {
122          set_error(ERR_OK);          set_error(ERR_OK);
123    
124          // Channel 15: Execute file name as command          // Channel 15: Execute file name as command
125          if (channel == 15) {          if (channel == 15) {
126                  execute_command(filename);                  execute_cmd(name, name_len);
127                  return ST_OK;                  return ST_OK;
128          }          }
129    
# Line 143  uint8 FSDrive::Open(int channel, char *f Line 133  uint8 FSDrive::Open(int channel, char *f
133                  file[channel] = NULL;                  file[channel] = NULL;
134          }          }
135    
136          if (filename[0] == '$')          if (name[0] == '#') {
                 return open_directory(channel, filename+1);  
   
         if (filename[0] == '#') {  
137                  set_error(ERR_NOCHANNEL);                  set_error(ERR_NOCHANNEL);
138                  return ST_OK;                  return ST_OK;
139          }          }
140    
141          return open_file(channel, filename);          if (name[0] == '$')
142                    return open_directory(channel, name + 1, name_len - 1);
143    
144            return open_file(channel, name, name_len);
145  }  }
146    
147    
# Line 159  uint8 FSDrive::Open(int channel, char *f Line 149  uint8 FSDrive::Open(int channel, char *f
149   *  Open file   *  Open file
150   */   */
151    
152  uint8 FSDrive::open_file(int channel, char *filename)  uint8 FSDrive::open_file(int channel, const uint8 *name, int name_len)
153  {  {
154          char plainname[NAMEBUF_LENGTH];          char plain_name[NAMEBUF_LENGTH];
155          int filemode = FMODE_READ;          int plain_name_len;
156          int filetype = FTYPE_PRG;          int mode = FMODE_READ;
157          bool wildflag = false;          int type = FTYPE_PRG;
158          char *mode = "rb";          int rec_len = 0;
159            parse_file_name(name, name_len, (uint8 *)plain_name, plain_name_len, mode, type, rec_len, true);
160          convert_filename(filename, plainname, &filemode, &filetype, &wildflag);  
161            // Channel 0 is READ, channel 1 is WRITE
162          // Channel 0 is READ PRG, channel 1 is WRITE PRG          if (channel == 0 || channel == 1) {
163          if (!channel) {                  mode = channel ? FMODE_WRITE : FMODE_READ;
164                  filemode = FMODE_READ;                  if (type == FTYPE_DEL)
165                  filetype = FTYPE_PRG;                          type = FTYPE_PRG;
166          }          }
167          if (channel == 1) {  
168                  filemode = FMODE_WRITE;          bool writing = (mode == FMODE_WRITE || mode == FMODE_APPEND);
169                  filetype = FTYPE_PRG;  
170          }          // Expand wildcards (only allowed on reading)
171            if (strchr(plain_name, '*') || strchr(plain_name, '?')) {
172          // Wildcards are only allowed on reading                  if (writing) {
         if (wildflag) {  
                 if (filemode != FMODE_READ) {  
173                          set_error(ERR_SYNTAX33);                          set_error(ERR_SYNTAX33);
174                          return ST_OK;                          return ST_OK;
175                    } else
176                            find_first_file(plain_name);
177                  }                  }
178                  find_first_file(plainname);  
179            // Relative files are not supported
180            if (type == FTYPE_REL) {
181                    set_error(ERR_UNIMPLEMENTED);
182                    return ST_OK;
183          }          }
184    
185          // Select fopen() mode according to file mode          // Select fopen() mode according to file mode
186          switch (filemode) {          const char *mode_str = "rb";
187                  case FMODE_READ:          switch (mode) {
                         mode = "rb";  
                         break;  
188                  case FMODE_WRITE:                  case FMODE_WRITE:
189                          mode = "wb";                          mode_str = "wb";
190                          break;                          break;
191                  case FMODE_APPEND:                  case FMODE_APPEND:
192                          mode = "ab";                          mode_str = "ab";
193                          break;                          break;
194          }          }
195    
# Line 205  uint8 FSDrive::open_file(int channel, ch Line 197  uint8 FSDrive::open_file(int channel, ch
197  #ifndef __riscos__  #ifndef __riscos__
198          if (chdir(dir_path))          if (chdir(dir_path))
199                  set_error(ERR_NOTREADY);                  set_error(ERR_NOTREADY);
200          else if ((file[channel] = fopen(plainname, mode)) != NULL) {          else if ((file[channel] = fopen(plain_name, mode_str)) != NULL) {
201                  if (filemode == FMODE_READ)     // Read and buffer first byte                  if (mode == FMODE_READ || mode == FMODE_M)      // Read and buffer first byte
202                          read_char[channel] = fgetc(file[channel]);                          read_char[channel] = fgetc(file[channel]);
203          } else          } else
204                  set_error(ERR_FILENOTFOUND);                  set_error(ERR_FILENOTFOUND);
# Line 216  uint8 FSDrive::open_file(int channel, ch Line 208  uint8 FSDrive::open_file(int channel, ch
208            char fullname[NAMEBUF_LENGTH];            char fullname[NAMEBUF_LENGTH];
209    
210            // On RISC OS make a full filename            // On RISC OS make a full filename
211            sprintf(fullname,"%s.%s",dir_path,plainname);            sprintf(fullname,"%s.%s",dir_path,plain_name);
212            if ((file[channel] = fopen(fullname, mode)) != NULL)            if ((file[channel] = fopen(fullname, mode)) != NULL)
213            {            {
214              if (filemode == FMODE_READ)              if (mode == FMODE_READ || mode == FMODE_M)
215              {              {
216                read_char[channel] = fgetc(file[channel]);                read_char[channel] = fgetc(file[channel]);
217              }              }
# Line 236  uint8 FSDrive::open_file(int channel, ch Line 228  uint8 FSDrive::open_file(int channel, ch
228    
229    
230  /*  /*
  *  Analyze file name, get access mode and type  
  */  
   
 void FSDrive::convert_filename(char *srcname, char *destname, int *filemode, int *filetype, bool *wildflag)  
 {  
         char *p, *q;  
         int i;  
   
         // Search for ':', p points to first character after ':'  
         if ((p = strchr(srcname, ':')) != NULL)  
                 p++;  
         else  
                 p = srcname;  
   
         // Convert char set of the remaining string -> destname  
         q = destname;  
         for (i=0; i<NAMEBUF_LENGTH && (*q++ = conv_from_64(*p++, true)); i++) ;  
   
         // Look for mode parameters seperated by ','  
         p = destname;  
         while ((p = strchr(p, ',')) != NULL) {  
   
                 // Cut string after the first ','  
                 *p++ = 0;  
   
                 switch (*p) {  
                         case 'p':  
                                 *filetype = FTYPE_PRG;  
                                 break;  
                         case 's':  
                                 *filetype = FTYPE_SEQ;  
                                 break;  
                         case 'r':  
                                 *filemode = FMODE_READ;  
                                 break;  
                         case 'w':  
                                 *filemode = FMODE_WRITE;  
                                 break;  
                         case 'a':  
                                 *filemode = FMODE_APPEND;  
                                 break;  
                 }  
         }  
   
         // Search for wildcards  
         *wildflag = (strchr(destname, '?') != NULL) || (strchr(destname, '*') != NULL);  
 }  
   
   
 /*  
231   *  Find first file matching wildcard pattern and get its real name   *  Find first file matching wildcard pattern and get its real name
232   */   */
233    
234  // Return true if name 'n' matches pattern 'p'  // Return true if name 'n' matches pattern 'p'
235  static bool match(char *p, char *n)  static bool match(const char *p, const char *n)
236  {  {
237          if (!*p)                // Null pattern matches everything          if (!*p)                // Null pattern matches everything
238                  return true;                  return true;
# Line 306  static bool match(char *p, char *n) Line 248  static bool match(char *p, char *n)
248          return !*n;          return !*n;
249  }  }
250    
251  void FSDrive::find_first_file(char *name)  void FSDrive::find_first_file(char *pattern)
252  {  {
253  #ifndef __riscos__  #ifndef __riscos__
254          DIR *dir;          DIR *dir;
# Line 322  void FSDrive::find_first_file(char *name Line 264  void FSDrive::find_first_file(char *name
264          while (de) {          while (de) {
265    
266                  // Match found? Then copy real file name                  // Match found? Then copy real file name
267                  if (match(name, de->d_name)) {                  if (match(pattern, de->d_name)) {
268                          strncpy(name, de->d_name, NAMEBUF_LENGTH);                          strncpy(pattern, de->d_name, NAMEBUF_LENGTH);
269                          closedir(dir);                          closedir(dir);
270                          return;                          return;
271                  }                  }
# Line 355  void FSDrive::find_first_file(char *name Line 297  void FSDrive::find_first_file(char *name
297   *  Open directory, create temporary file   *  Open directory, create temporary file
298   */   */
299    
300  uint8 FSDrive::open_directory(int channel, char *filename)  uint8 FSDrive::open_directory(int channel, const uint8 *pattern, int pattern_len)
301  {  {
302          char buf[] = "\001\004\001\001\0\0\022\042                \042 00 2A";          char buf[] = "\001\004\001\001\0\0\022\042                \042 00 2A";
303          char str[NAMEBUF_LENGTH];          char str[NAMEBUF_LENGTH];
         char pattern[NAMEBUF_LENGTH];  
304          char *p, *q;          char *p, *q;
305          int i;          int i;
306          int filemode;          int filemode;
# Line 372  uint8 FSDrive::open_directory(int channe Line 313  uint8 FSDrive::open_directory(int channe
313          struct stat statbuf;          struct stat statbuf;
314    
315          // Special treatment for "$0"          // Special treatment for "$0"
316          if (filename[0] == '0' && filename[1] == 0)          if (pattern[0] == '0' && pattern[1] == 0) {
317                  filename += 1;                  pattern++;
318                    pattern_len--;
319            }
320    
321          // Convert filename ('$' already stripped), filemode/type are ignored          // Skip everything before the ':' in the pattern
322          convert_filename(filename, pattern, &filemode, &filetype, &wildflag);          uint8 *t = (uint8 *)memchr(pattern, ':', pattern_len);
323            if (t)
324                    pattern = t + 1;
325    
326            // Convert pattern to ASCII
327            char ascii_pattern[NAMEBUF_LENGTH];
328            petscii2ascii(ascii_pattern, (const char *)pattern, NAMEBUF_LENGTH);
329    
330          // Open directory for reading and skip '.' and '..'          // Open directory for reading and skip '.' and '..'
331          if ((dir = opendir(dir_path)) == NULL) {          if ((dir = opendir(dir_path)) == NULL) {
# Line 396  uint8 FSDrive::open_directory(int channe Line 345  uint8 FSDrive::open_directory(int channe
345          // Create directory title          // Create directory title
346          p = &buf[8];          p = &buf[8];
347          for (i=0; i<16 && dir_title[i]; i++)          for (i=0; i<16 && dir_title[i]; i++)
348                  *p++ = conv_to_64(dir_title[i], false);                  *p++ = ascii2petscii(dir_title[i]);
349          fwrite(buf, 1, 32, file[channel]);          fwrite(buf, 1, 32, file[channel]);
350    
351          // Create and write one line for every directory entry          // Create and write one line for every directory entry
352          while (de) {          while (de) {
353    
354                  // Include only files matching the pattern                  // Include only files matching the ascii_pattern
355                  if (match(pattern, de->d_name)) {                  if (match(ascii_pattern, de->d_name)) {
356    
357                          // Get file statistics                          // Get file statistics
358                          chdir(dir_path);                          chdir(dir_path);
# Line 432  uint8 FSDrive::open_directory(int channe Line 381  uint8 FSDrive::open_directory(int channe
381                          *p++ = '\"';                          *p++ = '\"';
382                          q = p;                          q = p;
383                          for (i=0; i<16 && str[i]; i++)                          for (i=0; i<16 && str[i]; i++)
384                                  *q++ = conv_to_64(str[i], true);                                  *q++ = ascii2petscii(str[i]);
385                          *q++ = '\"';                          *q++ = '\"';
386                          p += 18;                          p += 18;
387    
# Line 460  uint8 FSDrive::open_directory(int channe Line 409  uint8 FSDrive::open_directory(int channe
409          unsigned char c;          unsigned char c;
410    
411          // Much of this is very similar to the original          // Much of this is very similar to the original
412          if ((filename[0] == '0') && (filename[1] == 0)) {filename++;}          if ((pattern[0] == '0') && (pattern[1] == 0)) {pattern++;}
413    
414          // Concatenate dir_path and pattern in buffer pattern ==> read subdirs!          // Concatenate dir_path and ascii_pattern in buffer ascii_pattern ==> read subdirs!
415          strcpy(pattern,dir_path); i = strlen(pattern); pattern[i++] = '.'; pattern[i] = 0;          strcpy(ascii_pattern,dir_path); i = strlen(ascii_pattern); ascii_pattern[i++] = '.'; ascii_pattern[i] = 0;
416          convert_filename(filename, pattern + i, &filemode, &filetype, &wildflag);          convert_filename(pattern, ascii_pattern + i, &filemode, &filetype, &wildflag);
417          p = pattern + i; q = p;          p = ascii_pattern + i; q = p;
418          do {c = *q++; if (c == '.') p = q;} while (c >= 32);          do {c = *q++; if (c == '.') p = q;} while (c >= 32);
419          *(p-1) = 0;  // separate directory-path and pattern          *(p-1) = 0;  // separate directory-path and ascii_pattern
420          if ((uint8)(*p) < 32) {*p = '*'; *(p+1) = 0;}          if ((uint8)(*p) < 32) {*p = '*'; *(p+1) = 0;}
421    
422          // We don't use tmpfile() -- problems involved!          // We don't use tmpfile() -- problems involved!
# Line 484  uint8 FSDrive::open_directory(int channe Line 433  uint8 FSDrive::open_directory(int channe
433    
434          do {          do {
435                  de.readno = 1;                  de.readno = 1;
436                  if (ReadDirNameInfo(pattern,&di,&de) != NULL)                  if (ReadDirNameInfo(ascii_pattern,&di,&de) != NULL)
437                          de.offset = -1;                          de.offset = -1;
438                  else if (de.readno > 0) {       // don't have to check for match here                  else if (de.readno > 0) {       // don't have to check for match here
439                          memset(buf,' ',31); buf[31] = 0;        // most of this: see above                          memset(buf,' ',31); buf[31] = 0;        // most of this: see above
# Line 601  uint8 FSDrive::Write(int channel, uint8 Line 550  uint8 FSDrive::Write(int channel, uint8
550  {  {
551          // Channel 15: Collect chars and execute command on EOI          // Channel 15: Collect chars and execute command on EOI
552          if (channel == 15) {          if (channel == 15) {
553                  if (cmd_len >= 40)                  if (cmd_len >= 58)
554                          return ST_TIMEOUT;                          return ST_TIMEOUT;
555    
556                  cmd_buffer[cmd_len++] = byte;                  cmd_buf[cmd_len++] = byte;
557    
558                  if (eoi) {                  if (eoi) {
559                          cmd_buffer[cmd_len] = 0;                          execute_cmd(cmd_buf, cmd_len);
560                          cmd_len = 0;                          cmd_len = 0;
                         execute_command(cmd_buffer);  
561                  }                  }
562                  return ST_OK;                  return ST_OK;
563          }          }
# Line 619  uint8 FSDrive::Write(int channel, uint8 Line 567  uint8 FSDrive::Write(int channel, uint8
567                  return ST_TIMEOUT;                  return ST_TIMEOUT;
568          }          }
569    
570          if (fputc(byte, file[channel]) == EOF) {          if (putc(byte, file[channel]) == EOF) {
571                  set_error(ERR_WRITEERROR);                  set_error(ERR_WRITE25);
572                  return ST_TIMEOUT;                  return ST_TIMEOUT;
573          }          }
574    
# Line 629  uint8 FSDrive::Write(int channel, uint8 Line 577  uint8 FSDrive::Write(int channel, uint8
577    
578    
579  /*  /*
580   *  Execute command string   *  Execute drive commands
581   */   */
582    
583  void FSDrive::execute_command(char *command)  // INITIALIZE
584    void FSDrive::initialize_cmd(void)
585  {  {
         switch (command[0]) {  
                 case 'I':  
586                          close_all_channels();                          close_all_channels();
                         set_error(ERR_OK);  
                         break;  
   
                 case 'U':  
                         if ((command[1] & 0x0f) == 0x0a) {  
                                 Reset();  
                         } else  
                                 set_error(ERR_SYNTAX30);  
                         break;  
   
                 case 'G':  
                         if (command[1] != ':')  
                                 set_error(ERR_SYNTAX30);  
                         else  
                                 chdir_cmd(&command[2]);  
                         break;  
   
                 default:  
                         set_error(ERR_SYNTAX30);  
         }  
587  }  }
588    
589    // VALIDATE
590  /*  void FSDrive::validate_cmd(void)
  *  Execute 'G' command  
  */  
   
 void FSDrive::chdir_cmd(char *dirpath)  
591  {  {
         char str[NAMEBUF_LENGTH];  
         char *p = str;  
   
         close_all_channels();  
   
         // G:. resets the directory path to its original setting  
         if (dirpath[0] == '.' && dirpath[1] == 0) {  
                 change_dir(orig_dir_path);  
         } else {  
   
                 // Convert directory name  
                 for (int i=0; i<NAMEBUF_LENGTH && (*p++ = conv_from_64(*dirpath++, false)); i++) ;  
   
                 if (!change_dir(str))  
                         set_error(ERR_NOTREADY);  
         }  
592  }  }
593    
594    
# Line 695  void FSDrive::Reset(void) Line 602  void FSDrive::Reset(void)
602          cmd_len = 0;          cmd_len = 0;
603          set_error(ERR_STARTUP);          set_error(ERR_STARTUP);
604  }  }
   
   
 /*  
  *  Conversion PETSCII->ASCII  
  */  
   
 uint8 FSDrive::conv_from_64(uint8 c, bool map_slash)  
 {  
         if ((c >= 'A') && (c <= 'Z') || (c >= 'a') && (c <= 'z'))  
                 return c ^ 0x20;  
         if ((c >= 0xc1) && (c <= 0xda))  
                 return c ^ 0x80;  
         if ((c == '/') && map_slash && ThePrefs.MapSlash)  
 #ifdef __riscos__  
                 return '.';     // directory separator is '.' in RO  
         if (c == '.') {return('_');}    // convert dot to underscore  
         if (c == ' ') {return(0xa0);}   // space --> hard space  
 #else  
                 return '\\';  
 #endif  
         return c;  
 }  
   
   
 /*  
  *  Conversion ASCII->PETSCII  
  */  
   
 uint8 FSDrive::conv_to_64(uint8 c, bool map_slash)  
 {  
         if ((c >= 'A') && (c <= 'Z') || (c >= 'a') && (c <= 'z'))  
                 return c ^ 0x20;  
 #ifdef __riscos__  
         if ((c == '.') && map_slash && ThePrefs.MapSlash)  
 #else  
         if ((c == '\\') && map_slash && ThePrefs.MapSlash)  
 #endif  
                 return '/';  
 #ifdef __riscos__  
         if (c == '_') {return('.');}    // convert underscore to dot  
         if (c == 0xa0) {return(' ');}   // hard space -> space  
 #endif  
         return c;  
 }  

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

Christian Bauer">Christian Bauer
ViewVC Help
Powered by ViewVC 1.1.15