Пример #1
0
/**
 * Check checksum
 */
int checksum_true(uint8_t *buf){
	uint8_t *eol;
	uint8_t checksum = 0, cs[3];
	if(*buf != '$' || !(eol = ustrchr(buf, '*'))){
		DBG("Wrong data: ");
		DBG(buf);
		DBG("\n");
		return 0;
	}
	while(++buf != eol)
		checksum ^= *buf;
	++buf;
	cs[0] = hex(checksum >> 4);
	cs[1] = hex(checksum & 0x0f);
	if(buf[0] == cs[0] && buf[1] == cs[1])
		return 1;
#ifdef EBUG
	cs[2] = 0;
	P("CHS, get ");
	P(buf);
	P(" need ");
	P(cs);
	usb_send('\n');
#endif
	return 0;
}
Пример #2
0
int paramfile::GetLine(){
	if (eof) return 0;
	if (!rline) return 1;
	if (NULL == fgets((char *)GivenLine,256,f)){
		eof = 1;
		return 0;
	}
	UNCH *p = ustrchr(GivenLine,'\n');
	if (NULL != p)p[0] = 0;
	lno++;
	return 1;
};
Пример #3
0
void HandleSub(XlateEntryData * xp){
	XlateEntryData* p = xp;
	UNCH /* boolean */ ccol[256];
	memset(ccol, FALSE, 256);
// for (int oc = 0; oc <= 255; oc++) ccol[oc] = FALSE;
	while (p != 0){ccol[p->c] = TRUE; p = p->f;}
	p = xp;
	while (p != 0) {
		UNCH * upos = ustrchr(UpperCharList, p->c),
			  * lpos = ustrchr(LowerCharList, p->c), ox;
		if ((upos != 0) || (lpos != 0)) {
			if (upos != 0) ox = *upos;
			else ox = *lpos;
		}
		if (!ccol[ox]){
			XlateEntryData* np = new XlateEntryData(ox, p);
			p->f = np;
			p = np;
			if (p->n != 0) HandleSub(p->n);
		}
		p = p->f;
	}
}
Пример #4
0
static bool_t csmins_deal(void)
{
	recv.offset = 0;
	uint8_t* ptr = ustrchr(recv.buf, ",");
	if (ptr != NULL)
	{
		ptr++;
		if (*ptr == 0x31)
		{
			return TRUE;
		}
	}
	gprs_info.gprs_state = SIM_ERROR;
	return FALSE;
}
Пример #5
0
static bool_t cgatt_deal(void)
{
	recv.offset = 0;
	uint8_t* ptr = ustrchr(recv.buf, ":");
	if (ptr != NULL)
	{
		ptr += 2;
		if (*ptr == 0x31)
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
	gprs_info.gprs_state = GPRS_NET_ERROR;
	return FALSE;
}
Пример #6
0
static bool_t cipmode_deal(void)
{
    recv.offset = 0;
	uint8_t* ptr = ustrchr(recv.buf, ":");
	if (ptr != NULL)
	{
		ptr += 2;
		if (*ptr == 0x31)
		{
			return TRUE;
		}
		else
		{
            write_fifo(CIPMODE, sizeof(CIPMODE) - 1);
			vTaskDelay(300 / portTICK_RATE_MS);
            if (my_strstr((const char*)recv.buf, (const char*)ATOK) != NULL)
                return TRUE;
            else
                return FALSE;
		}
	}
	return FALSE;
}
Пример #7
0
parseritem * myscanner::getitem(){
	UNCH work[100], strch, *tch, s[2];
	unsigned workpos;
#define EXPECTELE 1
#define EXPECTVAR 2
#define EXPECTNOTHING 0
	int specchar = EXPECTNOTHING;
	while (1) {
		switch (State) {
		case FILEEOF:
			return new myitem(ENDOFFILE, (*elup)[ENDOFFILE], 0);
		case PASTEND:
			break;
		case FINDSTART:
			while ((GivenLine[pos] == 0) || (GivenLine[pos] == COMMENTID)) {
				if (NULL == (GivenLine = pfile->Data())){
					State = FILEEOF;
					return new myitem(ENDOFFILE, (*elup)[ENDOFFILE], 0);
				}
				pos = 0;
			}
		case SKIPBLANKS:
			if ((GivenLine[pos] != ' ')&&(GivenLine[pos] != '\t')) State = WHATISIT;
			else pos++;
			specchar = EXPECTNOTHING;
			break;
		case WHATISIT:
			if ((GivenLine[pos] == 0) || (GivenLine[pos] == COMMENTID)) {
				State = FINDSTART;
				if (NULL == (GivenLine = pfile->Data()))
					State = FILEEOF;
				pos = 0;
				return new myitem(STATEMENTEND, (*elup)[STATEMENTEND], pfile->LineNo()-1);
			}
			else if (GivenLine[pos] == ANNOUNCEELE) {
				strch = GivenLine[pos++];
				specchar = EXPECTELE;
				State = MUSTBEALPHA;
			}
			else if (GivenLine[pos] == ANNOUNCEVAR) {
				strch = GivenLine[pos++];
				specchar = EXPECTVAR;
				State = MUSTBEALPHA;
			}
			else if ((isalpha(GivenLine[pos]))||(GivenLine[pos]=='\\')) {
				State = COLLECTALPHA;
				workpos = 0;
			}
			else if ((GivenLine[pos] == '"')||(GivenLine[pos] == '\'')){
				State = COLLECTSTRING;
				workpos = 0;
				strch = GivenLine[pos++];
			}
			else if (NULL != (tch = ustrchr(singlesstr, GivenLine[pos]))){
				State = SKIPBLANKS;
				work[1] = 0; work[0] = GivenLine[pos++];
				return new myitem(SINGLESOFFSET + (tch - singlesstr), work, pfile->LineNo());
			}
			else if ((GivenLine[pos]>='0')&&(GivenLine[pos]<='9') ) {
				State = COLLECTNUMBER;
				workpos = 0;
			}
			else {
				/*RES OLD MSG 587
				File %0: Unrecognized character "%1" found in line %2.
				*/
				ResFile->MsgData(epmfilename);
				ResFile->MsgData((unsigned short)GivenLine[pos]);
				ResFile->MsgData(pfile->LineNo());
				ResFile->PutResError(/*RES REM INS*/ 587);
				s[1] = 0; s[0] = GivenLine[pos];
				return new myitem(9999, s, pfile->LineNo());
			}
			break;
		case MUSTBEALPHA:
			if ((isalpha(GivenLine[pos]))||(GivenLine[pos]=='\\')) {
				State = COLLECTALPHA;
				workpos = 0;
			}
			else {
				/*RES OLD MSG 599
				File %0: A name does not follow "%1" on in line %2.
				*/
				ResFile->MsgData(epmfilename);
				ResFile->MsgData(strch);
				ResFile->MsgData(pfile->LineNo());
				ResFile->PutResError(/*RES REM INS*/ 599);
				s[1] = 0; s[0] = strch;
				return new myitem(9999, s, pfile->LineNo());
			}
			break;
		case COLLECTALPHA:
			if (IsNameChar(GivenLine[pos]))work[workpos++] = toupper(GivenLine[pos++]);
         else if (GivenLine[pos] == '\\'){
            if (GivenLine[pos+1] != 0)pos++;
            work[workpos++] = GivenLine[pos++];
         }
			else {
				work[workpos] = 0;
				State = CHECKALPHA;
			}
			break;
		case CHECKALPHA:
			etd *fndetd;
  //		basevalue *fndid;
			int rslt;
			varname *vn;
			State = SKIPBLANKS;
			if (specchar == EXPECTELE){
				if ((fndetd = IsElementName(work)) != NULL)
					return new etditem(ELEMENTNAME, work, pfile->LineNo(), fndetd);
				/*RES OLD MSG 600
				File %0: "%1" is not an element name, on line %2.
				*/
				ResFile->MsgData(epmfilename);
				ResFile->MsgData(work);
				ResFile->MsgData(pfile->LineNo());
				ResFile->PutResError(/*RES REM INS*/ 600);
				return new myitem(9999, work, pfile->LineNo());
			}
			else if (specchar == EXPECTVAR){
				if ((vn = IsVarName(globalvars,work)) != NULL)
					return new varitem(VARIABLENAME, work, pfile->LineNo(), vn);
				/*RES OLD MSG 601
				File %0: "%1" is not a global variable or TACTid name, on line %2.
				*/
				ResFile->MsgData(epmfilename);
				ResFile->MsgData(work);
				ResFile->MsgData(pfile->LineNo());
				ResFile->PutResError(/*RES REM INS*/ 601);
				return new myitem(9999, work, pfile->LineNo());
			}
			if (0 != (rslt = slup->Lookup(work)))
				return new myitem(STRINGSSTART + rslt, work, pfile->LineNo());
			else
			if ((fndetd = IsElementName(work)) != NULL)
				return new etditem(ELEMENTNAME, work, pfile->LineNo(), fndetd);
			if ((vn = IsVarName(localvars,work)) != NULL)
				return new varitem(VARIABLENAME, work, pfile->LineNo(), vn);
			if ((vn = IsVarName(globalvars,work)) != NULL)
				return new varitem(VARIABLENAME, work, pfile->LineNo(), vn);
			else
				return new myitem(UNDECLAREDNAME, work, pfile->LineNo());
		case COLLECTSTRING:
			if ((GivenLine[pos] == COMMENTID)|(GivenLine[pos] == 0)) {
				/*RES OLD MSG 584
				File %0: A string without a closing character was found on line %1
				*/
				ResFile->MsgData(epmfilename);
				ResFile->MsgData(pfile->LineNo());
				ResFile->PutResError(/*RES REM INS*/ 584);
				return new myitem(9999, work, pfile->LineNo());
			}
			if (GivenLine[pos] == strch)
			{
				pos++;
				State = SKIPBLANKS;
				work[workpos] = 0;
				return new myitem(STRING, work, pfile->LineNo());
			}
			else work[workpos++] = GivenLine[pos++];
			break;
		case COLLECTNUMBER:
			if ((GivenLine[pos]>='0')&&(GivenLine[pos]<='9') ) work[workpos++] = GivenLine[pos++];
			else {
				State = SKIPBLANKS;
				work[workpos] = 0;
				return new myitem(NUMBER, work, pfile->LineNo());
			}
			break;
		}
	}
};
Пример #8
0
/* fs_flist_putter:
 *  Callback routine for for_each_file() to fill the file selector listbox.
 */
static void fs_flist_putter(AL_CONST char *str, int attrib, int param)
{
   char ext_tokens[32];
   char *s, *ext, *tok, *name;
   char tmp[512], tmp2[32];
   int c, c2, i, k, sign;

   /* attribute flags (rhsda order)
    * 0 = not required, 1 = must be set, -1 = must be unset
    */
   int attr_flag[5+5] = {
      0, -1, -1, 0, 0,
      FA_RDONLY, FA_HIDDEN, FA_SYSTEM, FA_DIREC, FA_ARCH
   };

   c = usetc(ext_tokens, ' ');
   c += usetc(ext_tokens+c, ',');
   c += usetc(ext_tokens+c, ';');
   usetc(ext_tokens+c, 0);

   s = get_filename(str);
   fix_filename_case(s);

   if (fext) {
      ustrcpy(tmp, fext);
      ustrtok(tmp, ext_tokens);
      c = (ustrtok(NULL, ext_tokens) ? 1 : 0);
      if (!c) {
	 if (!ustrchr(fext, '/'))
	    c = 1;
      }

      if (c && (!(attrib & FA_DIREC))) {
	 ustrcpy(tmp, fext);
	 ext = get_extension(s);
	 tok = ustrtok(tmp, ext_tokens);

	 while (tok) {
	    if (ustricmp(ext, tok) == 0)
	       break;

	    tok = ustrtok(NULL, ext_tokens);
	 }

	 if (!tok)
	    return;
      }

      c = usetc(ext_tokens, ' ');
      c += usetc(ext_tokens+c, ',');
      c += usetc(ext_tokens+c, ';');
      c += usetc(ext_tokens+c, '/');
      usetc(ext_tokens+c, 0);

      ustrcpy(tmp, fext);
      tok = ustrchr(tmp, '/');

      if (tok)
	 tok = ustrtok(tok, ext_tokens);

      if (tok) {
	 sign = 1;
	 c = usetc(tmp2, 'r');
	 c += usetc(tmp2+c, 'h');
	 c += usetc(tmp2+c, 's');
	 c += usetc(tmp2+c, 'd');
	 c += usetc(tmp2+c, 'a');
	 c += usetc(tmp2+c, '+');
	 c += usetc(tmp2+c, '-');
	 usetc(tmp2+c, 0);

	 /* scan the string */
	 i = 0;
	 while ((c = utolower(ugetat(tok, i)))) {
	    k = 0;
	    while ((c2 = ugetat(tmp2, k))!=0) {
	       if (c == c2) {
		  if (k<5) {
		     attr_flag[k] = sign;
		     break;
		  }
		  else
		     sign = (k==5) ? 1 : -1;
	       }
	       k++;
	    }
	    i++;
	 }
      }
   }

   /* check if file attributes match */
   if (!(attr_flag[3+5] & attrib)) {
      /* if not a directory, we check all attributes except FA_DIREC */
      for (c=0; c<5; c++) {
	 if (c == 3)
	    continue;
	 if ((attr_flag[c] == 1) && (!(attrib & attr_flag[c+5])))
	    return;
	 if ((attr_flag[c] == -1) && (attrib & attr_flag[c+5]))
	    return;
      }
   }
   else {
      /* if a directory, we check only FA_DIREC */
      if (attr_flag[3] == -1)
	 return;
   }

   if ((flist->size < FLIST_SIZE) && ((ugetc(s) != '.') || (ugetat(s, 1)))) {
      name = malloc(ustrsizez(s) + ((attrib & FA_DIREC) ? ucwidth(OTHER_PATH_SEPARATOR) : 0));
      if (!name)
	 return;

      for (c=0; c<flist->size; c++) {
	 if (ugetat(flist->name[c], -1) == OTHER_PATH_SEPARATOR) {
	    if (attrib & FA_DIREC)
	       if (ustrfilecmp(s, flist->name[c]) < 0)
		  break;
	 }
	 else {
	    if (attrib & FA_DIREC)
	       break;
	    if (ustrfilecmp(s, flist->name[c]) < 0)
	       break;
	 }
      }

      for (c2=flist->size; c2>c; c2--)
	 flist->name[c2] = flist->name[c2-1];

      flist->name[c] = name;
      ustrcpy(flist->name[c], s);

      if (attrib & FA_DIREC)
	 put_backslash(flist->name[c]);

      flist->size++;
   }
}
Пример #9
0
/**
 * file_open - open a file on given secondary
 * @secondary: secondary address used in OPEN call
 *
 * This function opens the file named in command_buffer on the given
 * secondary address. All special names and prefixes/suffixed are handled
 * here, e.g. $/#/@/,S,W
 */
void file_open(uint8_t secondary) {
  buffer_t *buf;
  uint8_t i = 0;
  uint8_t recordlen = 0;

  /* If the secondary is already in use, close the existing buffer */
  buf = find_buffer(secondary);
  if (buf != NULL) {
    /* FIXME: What should we do if an error occurs? */
    cleanup_and_free_buffer(buf);
  }

  /* Assume everything will go well unless proven otherwise */
  set_error(ERROR_OK);

  /* Strip 0x0d characters from end of name (C2BD-C2CA) */
  if (command_length > 1) {
    if (command_buffer[command_length-1] == 0x0d)
      command_length -= 1;
    else if (command_buffer[command_length-2] == 0x0d)
      command_length -= 2;
  }

  /* Clear the remainder of the command buffer, simplifies parsing */
  memset(command_buffer+command_length, 0, sizeof(command_buffer)-command_length);

  uart_trace(command_buffer,0,command_length);

  /* Direct access? */
  if (command_buffer[0] == '#') {
    open_buffer(secondary);
    return;
  }

  /* Parse type+mode suffixes */
  uint8_t *ptr = command_buffer;
  enum open_modes mode = OPEN_READ;
  uint8_t filetype = TYPE_DEL;

  while(i++ < 2 && *ptr && (ptr = ustrchr(ptr, ','))) {
    *ptr = 0;
    ptr++;
    switch (*ptr) {
    case 0:
      break;

    case 'R': /* Read */
      mode = OPEN_READ;
      break;

    case 'W': /* Write */
      mode = OPEN_WRITE;
      break;

    case 'A': /* Append */
      mode = OPEN_APPEND;
      break;

    case 'M': /* Modify */
      mode = OPEN_MODIFY;
      break;

    case 'D': /* DEL */
      filetype = TYPE_DEL;
      break;

    case 'S': /* SEQ */
      filetype = TYPE_SEQ;
      break;

    case 'P': /* PRG */
      filetype = TYPE_PRG;
      break;

    case 'U': /* USR */
      filetype = TYPE_USR;
      break;

    case 'L': /* REL */
      filetype = TYPE_REL;
      mode = OPEN_WRITE;
      if((ptr = ustrchr(ptr, ',')))
        recordlen = *(++ptr);
      i = 2;  // stop the scan
      break;
    }
  }

  /* Load directory? */
  if (command_buffer[0] == '$') {
    load_directory(secondary);
    return;
  }

  /* Parse path+partition numbers */
  uint8_t *fname;
  int8_t res;
  cbmdirent_t dent;
  path_t path;

  /* Parse path and file name */
  if (parse_path(command_buffer, &path, &fname, 0))
      return;

#ifdef CONFIG_M2I
  /* For M2I only: Remove trailing spaces from name */
  if (partition[path.part].fop == &m2iops) {
    res = ustrlen(fname);
    while (--res && fname[res] == ' ')
      fname[res] = 0;
  }
#endif

  /* Filename matching */
  if (opendir(&matchdh, &path))
    return;

  do {
    res = next_match(&matchdh, fname, NULL, NULL, FLAG_HIDDEN, &dent);
    if (res > 0)
      /* Error, abort */
      return;

    /* Don't match on DEL or DIR */
    if ((dent.typeflags & TYPE_MASK) != TYPE_DEL &&
        (dent.typeflags & TYPE_MASK) != TYPE_DIR)
      break;

    /* But do match if it's for writing */
    if (mode == OPEN_WRITE || secondary == 1)
      break;
  } while (res == 0);

  if(res && filetype == TYPE_REL && !recordlen) {
    set_error(ERROR_SYNTAX_UNABLE);
    return;
  }

  /* If match found is a REL... */
  if(!res && (dent.typeflags & TYPE_MASK) == TYPE_REL) {
    /* requested type must be REL or DEL */
    if(filetype != TYPE_REL && filetype != TYPE_DEL) {
      set_error(ERROR_FILE_TYPE_MISMATCH);
      return;
    }
    filetype = TYPE_REL;
    mode = OPEN_MODIFY;
  }

  /* Force mode+type for secondaries 0/1 */
  switch (secondary) {
  case 0:
    mode = OPEN_READ;
    if (filetype == TYPE_DEL)
      filetype = TYPE_PRG;
    break;

  case 1:
    mode = OPEN_WRITE;
    if (filetype == TYPE_DEL)
      filetype = TYPE_PRG;
    break;

  default:
    if (filetype == TYPE_DEL)
      filetype = TYPE_SEQ;
  }

  if (mode == OPEN_WRITE) {
    if (res == 0) {
      /* Match found */
      if (command_buffer[0] == '@') {
        /* Make sure there is a free buffer to open the new file later */
        if (!check_free_buffers()) {
          set_error(ERROR_NO_CHANNEL);
          return;
        }

        /* Copy dent because file_delete may change it */
        cbmdirent_t dentcopy = dent;

        /* Rewrite existing file: Delete the old one */
        if (file_delete(&path, &dentcopy) == 255)
          return;

        /* Force fatops to create a new name based on the (long) CBM- */
        /* name instead of creating one with the old SFN and no LFN.  */
        if (dent.opstype == OPSTYPE_FAT || dent.opstype == OPSTYPE_FAT_X00)
          dent.pvt.fat.realname[0] = 0;
      } else {
        /* Write existing file without replacement: Raise error */
        set_error(ERROR_FILE_EXISTS);
        return;
      }
    } else {
      /* Normal write or non-existing rewrite */
      /* Doesn't exist: Copy name to dent */
      memset(&dent, 0, sizeof(dent));
      ustrncpy(dent.name, fname, CBM_NAME_LENGTH);
      set_error(ERROR_OK); // because first_match has set FNF
    }
  } else if (res != 0) {
    /* File not found */
    set_error(ERROR_FILE_NOT_FOUND);
    return;
  }

  /* Grab a buffer */
  buf = alloc_buffer();
  if (!buf)
    return;

  buf->secondary = secondary;

  if(filetype == TYPE_REL) {
    display_filename_write(path.part,CBM_NAME_LENGTH,dent.name);
    open_rel(&path, &dent, buf, recordlen, (mode == OPEN_MODIFY));
    return;
  }

  switch (mode) {
  case OPEN_MODIFY:
  case OPEN_READ:
    /* Modify is the same as read, but allows reading *ed files.        */
    /* FAT doesn't have anything equivalent, so both are mapped to READ */
    display_filename_read(path.part,CBM_NAME_LENGTH,dent.name);
    open_read(&path, &dent, buf);
    break;

  case OPEN_WRITE:
  case OPEN_APPEND:
    display_filename_write(path.part,CBM_NAME_LENGTH,dent.name);
    open_write(&path, &dent, filetype, buf, (mode == OPEN_APPEND));
    break;
  }
}
Пример #10
0
/**
 * load_directory - Prepare directory generation and create header
 * @secondary: secondary address used for reading the directory
 *
 * This function prepeares directory reading and fills the buffer
 * with the header line of the directory listing.
 * BUG: There is a not-well-known feature in the 1541/1571 disk
 * drives (and possibly others) that returns unparsed directory
 * sectors if $ is opened with a secondary address != 0. This
 * is not emulated here.
 */
static void load_directory(uint8_t secondary) {
  buffer_t *buf;
  path_t path;
  uint8_t pos=1;

  buf = alloc_buffer();
  if (!buf)
    return;

  uint8_t *name;

  buf->secondary = secondary;
  buf->read      = 1;
  buf->lastused  = 31;

  if (command_length > 2 && secondary == 0) {
    if(command_buffer[1]=='=') {
      if(command_buffer[2]=='P') {
        /* Parse Partition Directory */

        /* copy static header to start of buffer */
        memcpy_P(buf->data, dirheader, sizeof(dirheader));
        memcpy_P(buf->data + 32, syspart_line, sizeof(syspart_line));
        buf->lastused  = 63;

        /* set partition number */
        buf->data[HEADER_OFFSET_DRIVE] = max_part;

        /* Let the refill callback handle everything else */
        buf->refill = pdir_refill;

        if(command_length>3) {
          /* Parse the name pattern */
          if (parse_path(command_buffer+3, &path, &name, 0))
            return;

          buf->pvt.pdir.matchstr = name;
        }
        stick_buffer(buf);

        return;
      } else if(command_buffer[2]=='T') {
        buf->pvt.dir.format = DIR_FMT_CMD_SHORT;
        pos=3;
      }
    }
  }

  if (command_buffer[pos]) { /* do we have a path to scan? */
    if (command_length > 2) {
      /* Parse the name pattern */
      if (parse_path(command_buffer+pos, &path, &name, 0))
        return;

      if (opendir(&buf->pvt.dir.dh, &path))
        return;

      buf->pvt.dir.matchstr = name;

      /* Check for a filetype match */
      name = ustrchr(name, '=');
      if (name != NULL) {
        *name++ = 0;
        switch (*name) {
        case 'S':
          buf->pvt.dir.filetype = TYPE_SEQ;
          break;

        case 'P':
          buf->pvt.dir.filetype = TYPE_PRG;
          break;

        case 'U':
          buf->pvt.dir.filetype = TYPE_USR;
          break;

        case 'R':
          buf->pvt.dir.filetype = TYPE_REL;
          break;

        case 'C': /* This is guessed, not verified */
          buf->pvt.dir.filetype = TYPE_CBM;
          break;

        case 'B': /* CMD compatibility */
        case 'D': /* Specifying DEL matches everything anyway */
          buf->pvt.dir.filetype = TYPE_DIR;
          break;

        case 'H': /* Extension: Also show hidden files */
          buf->pvt.dir.filetype = FLAG_HIDDEN;
          break;
        }
        if(buf->pvt.dir.filetype) {
          name++;
          if(*name++ != ',') {
            goto scandone;
          }
        }
        while(*name) {
          switch(*name++) {
          case '>':
            if(parse_date(&date_match_start,&name))
              goto scandone;
            if(date_match_start.month && date_match_start.day) // ignore 00/00/00
              buf->pvt.dir.match_start = &date_match_start;
            break;
          case '<':
            if(parse_date(&date_match_end,&name))
              goto scandone;
            if(date_match_end.month && date_match_end.day) // ignore 00/00/00
              buf->pvt.dir.match_end = &date_match_end;
            break;
          case 'L':
            /* don't switch to long format if 'N' has already been sent */
            if(buf->pvt.dir.format != DIR_FMT_CBM)
              buf->pvt.dir.format = DIR_FMT_CMD_LONG;
            break;
          case 'N':
            buf->pvt.dir.format=DIR_FMT_CBM; /* turn off extended listing */
            break;
          default:
            goto scandone;
          }
          if(*name && *name++ != ',') {
            goto scandone;
          }
        }
      }
    } else {
      /* Command string is two characters long, parse the drive */
      if (command_buffer[1] == '0')
        path.part = current_part;
      else
        path.part = command_buffer[1] - '0' - 1;
      if (path.part >= max_part) {
        set_error(ERROR_DRIVE_NOT_READY);
        return;
      }
      path.dir = partition[path.part].current_dir;
      if (opendir(&buf->pvt.dir.dh, &path))
        return;
    }
  } else {
    path.part = current_part;
    path.dir  = partition[path.part].current_dir;  // if you do not do this, get_label will fail below.
    if (opendir(&buf->pvt.dir.dh, &path))
      return;
  }

scandone:
  if (secondary != 0) {
    /* Raw directory */

    if (partition[path.part].fop == &d64ops) {
      /* No need to fake it for D64 files */
      d64_raw_directory(&path, buf);
      return;
    }

    /* prepare a fake BAM sector */
    memset(buf->data, 0, 256);
    memset(buf->data + BAM_OFFSET_NAME - 2, 0xa0, BAM_A0_AREA_SIZE);

    /* fill label and id */
    if (dir_label(&path, buf->data + BAM_OFFSET_NAME - 2))
      return;

    if (disk_id(&path, buf->data + BAM_OFFSET_ID - 2))
      return;

    /* change padding of label and id to 0xa0 */
    name = buf->data + BAM_OFFSET_NAME - 2 + CBM_NAME_LENGTH;
    while (*--name == ' ')
      *name = 0xa0;

    if (buf->data[BAM_OFFSET_ID+2-2] == 0x20)
      buf->data[BAM_OFFSET_ID+2-2] = 0xa0;

    /* DOS version marker */
    buf->data[0] = 'A';

    buf->refill = rawdir_refill;
    buf->lastused = 253;
  } else {

    /* copy static header to start of buffer */
    memcpy_P(buf->data, dirheader, sizeof(dirheader));

    /* set partition number */
    buf->data[HEADER_OFFSET_DRIVE] = path.part+1;

    /* read directory name */
    if (dir_label(&path, buf->data+HEADER_OFFSET_NAME))
      return;

    /* read id */
    if (disk_id(&path,buf->data+HEADER_OFFSET_ID))
      return;

    /* Let the refill callback handle everything else */
    buf->refill = dir_refill;
  }

  /* Keep the buffer around */
  stick_buffer(buf);

  return;

}