Пример #1
0
static void ultrfrm( int parcnt, genpar *pars, void *d0, void *d1, mapevalenviron* mapenv, evalcontext* ecntxt )
{
  maptyp mp, mp0;
  int mtyp;
  solidtyp sol;
  implinst coercf;

  mp0 = mp = *(maptyp*)pars[1].parp;
  sol = *(solidtyp*)pars[0].parp;
  mtyp = mp->type;
  if ( mtyp != ULtrf3 )
    if ( coercf = coercible( ULtrf3, mtyp, -1 ) )
      mp0 = newmap( ULtrf3, 1, pars+1, 0, coercf, ecntxt, 0 );
    else
      ecntxt->cycles->errormsg( 149 );
  if ( ecntxt->cycles->error )
  {
    soldel( &sol );
    delitem( ULmap, &mp );
    return;
  }
  mp = mp0;
  if ( !sol->ttyp )
  {
    sol->ttyp = ULmap;
    sol->trf.trfi = mp;
  }
  else
  {
    *(maptyp*)pars[1].parp = mp;
    if ( sol->ttyp == ULmap )
    {
      *(maptyp*)pars[0].parp = sol->trf.trfi;
      pars[0].type = ULmap;
    }
    else
    {
      *(trf3typ*)pars[0].parp = sol->trf.trfe;
      pars[0].type = ULtrf3;
    }
    sol->ttyp = ULmap;
    sol->trf.trfi = newmap( ULtrf3, 2, pars, 0, (implinst)ult3prd, ecntxt, 0 );
    if ( mp->idep & DEP3c )
      sol->trf.trfi->mpar[1].ppeval = true;
  }
  if ( ecntxt->cycles->error )
  {
    soldel( &sol );
    delitem( ULmap, &mp );
  }
  ecntxt->stacks->pushand( ULsol, &sol );
}
Пример #2
0
File *getfinaltarget(File *file)
{
    Map *linkmap = newmap();
    if (!linkmap) {
        errorf("Out of memory?\n");
        return NULL;
    }
    File *target = NULL;
    while (isstat(file) && islink(file)) {
        target = gettarget(file);
        if (!target) {
            errorf("Cannot determine target of %s for %s\n", getname(file));
            break;
        }
        if (inmap(linkmap, getinode(target))) {
            errorf("Symlink loop in %s\n", getname(file));
            /* no file to stat, but want to print the name field */
            target = NULL;
            break;
        } else {
            set(linkmap, (uintmax_t)getinode(target), NULL);
        }
        file = target;
    }
    freemap(linkmap);
    return target;
}
Пример #3
0
TEST_F(HashTableTest, TestIterator1)
{
    Int32HashMap newmap(5);

    newmap.put(1, 10);
    newmap.put(2, 20);
    newmap.put(3, 30);

    Int32HashMap::Iterator it = newmap.begin();

    // TODO check values
    EXPECT_NE(it, newmap.end());
    const Int32HashMap::HashTableEntry& entry1 = *(it++);
    EXPECT_EQ(entry1.key * 10, entry1.value);

    EXPECT_NE(it, newmap.end());
    const Int32HashMap::HashTableEntry& entry2 = *(it++);
    EXPECT_EQ(entry2.key * 10, entry2.value);

    EXPECT_NE(it, newmap.end());
    const Int32HashMap::HashTableEntry& entry3 = *(it++);
    EXPECT_EQ(entry3.key * 10, entry3.value);

    EXPECT_EQ(it, newmap.end());
}
Пример #4
0
TEST_F(HashTableTest, TestIterator2)
{
    Int32HashMap newmap(5);

    newmap.put(1, 10);
    newmap.put(2, 20);
    newmap.put(3, 30);

    Int32HashMap::Iterator it = newmap.begin();
    capu::Pair<capu::int32_t, capu::int32_t> pair;

    EXPECT_NE(it, newmap.end());

    EXPECT_EQ((*it).key * 10, (*it).value);
    it++;

    EXPECT_TRUE(it != newmap.end());
    const Int32HashMap::HashTableEntry& entry2 = *it;
    EXPECT_EQ(entry2.key * 10, entry2.value);
    it++;

    EXPECT_NE(it, newmap.end());
    EXPECT_EQ((*it).key * 10, (*it).value);
    it++;

    EXPECT_TRUE(it == newmap.end());
}
Пример #5
0
void
setcor(void)
{
	int i;

	if (cormap) {
		for (i = 0; i < cormap->nsegs; i++)
			if (cormap->seg[i].inuse)
				close(cormap->seg[i].fd);
	}

	fcor = getfile(corfil, 2, ORDWR);
	if (fcor <= 0) {
		if (cormap)
			free(cormap);
		cormap = dumbmap(-1);
		return;
	}
	if(pid > 0) {	/* provide addressability to executing process */
		cormap = attachproc(pid, kflag, fcor, &fhdr);
		if (!cormap)
			cormap = dumbmap(-1);
	} else {
		cormap = newmap(cormap, 2);
		if (!cormap)
			cormap = dumbmap(-1);
		setmap(cormap, fcor, fhdr.txtaddr, fhdr.txtaddr+fhdr.txtsz, fhdr.txtaddr, "text");
		setmap(cormap, fcor, fhdr.dataddr, 0xffffffff, fhdr.dataddr, "data");
	}
	kmsys();
	return;
}
Пример #6
0
static void ultrfr0( int parcnt, genpar *pars, void *d0, void *d1, mapevalenviron* mapenv, evalcontext* ecntxt )
{
  trf3typ trf;
  solidtyp sol;

  trf = *(trf3typ*)pars[1].parp;
  sol = *(solidtyp*)pars[0].parp;
  if ( sol->ttyp == ULmap )
  {
    pars[0].type = ULmap;
    *(maptyp*)pars[0].parp = sol->trf.trfi;
    sol->trf.trfi = newmap( ULtrf3, 2, pars, 0, (implinst)ult3prd, ecntxt, 0 );
    if ( ecntxt->cycles->error )
    {
      soldel( &sol );
      delitem( ULmap, pars[0].parp );
    }
  }
  else if ( sol->ttyp == ULtrf3 )
  {
    sethomo4( sol->trf.trfe.hom &= trf.hom );
    mat4mulx( sol->trf.trfe.tr, trf.tr );
  }
  else
  {
    sol->ttyp = ULtrf3;
    sol->trf.trfe = trf;
  }
  ecntxt->stacks->pushand( ULsol, &sol );
}
Пример #7
0
boolean Arpege::ChangePAT(int value)
{
  boolean ret = false;
  int newValue;

  switch(Mode)
  {
  case MODE_PATT:

    newValue = PatLed.Map(value);
    if ( newValue > 0 )
    {
      newValue--;
      if ( is_mode_write )
      {
        uint16_t masq =  1 << newValue;
        if ( ( Tracks[CurArp].Pattern & masq ) == masq )
          Tracks[CurArp].Pattern &= ~masq;
        else
          Tracks[CurArp].Pattern |= masq;
      }
      else
      {
        if ( newValue < NB_ARP_TRACK)
        {
          if (is_played==PLAYED)
          {
            NextArp = newValue;
          }
          else
          {
            if ( IsOn ) EventOff();
            ret = true;
            CurArp = newValue;
            DessinPage();
            UpdatePattern();
          }
        }
      }
    }
    break;

  case MODE_SONG:

    newValue = newmap(value, 0, NB_TR_SONG - 5);
    if ( newValue != CurTrSong )
    {
      ret = true;
      CurTrSong = newValue;
      DessinPage();
    }
    break;
  }


}
Пример #8
0
Map*
attachproc(int pid, int kflag, int corefd, Fhdr *fp)
{
	char buf[64], *regs;
	int fd;
	Map *map;
	uvlong n;

	map = newmap(0, 4);
	if (!map)
		return 0;
	if(kflag)
		regs = "kregs";
	else
		regs = "regs";
	if (mach->regsize) {
		sprint(buf, "/proc/%d/%s", pid, regs);
		fd = open(buf, ORDWR);
		if(fd < 0)
			fd = open(buf, OREAD);
		if(fd < 0) {
			free(map);
			return 0;
		}
		setmap(map, fd, 0, mach->regsize, 0, "regs");
	}
	if (mach->fpregsize) {
		sprint(buf, "/proc/%d/fpregs", pid);
		fd = open(buf, ORDWR);
		if(fd < 0)
			fd = open(buf, OREAD);
		if(fd < 0) {
			close(map->seg[0].fd);
			free(map);
			return 0;
		}
		setmap(map, fd, mach->regsize, mach->regsize+mach->fpregsize, 0, "fpregs");
	}
	setmap(map, corefd, fp->txtaddr, fp->txtaddr+fp->txtsz, fp->txtaddr, "text");
	if(kflag || fp->dataddr >= mach->utop) {
		setmap(map, corefd, fp->dataddr, ~0, fp->dataddr, "data");
		return map;
	}
	n = stacktop(pid);
	if (n == 0) {
		setmap(map, corefd, fp->dataddr, mach->utop, fp->dataddr, "data");
		return map;
	}
	setmap(map, corefd, fp->dataddr, n, fp->dataddr, "data");
	return map;
}
Пример #9
0
/*===========================================================================*
 *				do_newmap				     *
 *===========================================================================*/
int do_newmap(struct proc * caller, message * m_ptr)
{
/* Handle sys_newmap().  Fetch the memory map. */
  struct proc *rp;	/* process whose map is to be loaded */
  struct mem_map *map_ptr;	/* virtual address of map inside caller */
  int proc_nr;

  map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
  if (! isokendpt(m_ptr->PR_ENDPT, &proc_nr)) return(EINVAL);
  if (iskerneln(proc_nr)) return(EPERM);
  rp = proc_addr(proc_nr);

  return newmap(caller, rp, map_ptr);
}
Пример #10
0
// FIXME long long
Epetra_BlockMap
Epetra_Util::Create_OneToOne_BlockMap(const Epetra_BlockMap& usermap,
              bool high_rank_proc_owns_shared)
{
// FIXME long long

  //if usermap is already 1-to-1 then we'll just return a copy of it.
  if (usermap.IsOneToOne()) {
    Epetra_BlockMap newmap(usermap);
    return(newmap);
  }

  int myPID = usermap.Comm().MyPID();
  Epetra_Directory* directory = usermap.Comm().CreateDirectory(usermap);

  int numMyElems = usermap.NumMyElements();
  const int* myElems = usermap.MyGlobalElements();

  int* owner_procs = new int[numMyElems*2];
  int* sizes = owner_procs+numMyElems;

  directory->GetDirectoryEntries(usermap, numMyElems, myElems, owner_procs,
         0, sizes, high_rank_proc_owns_shared);

  //we'll fill a list of map-elements which belong on this processor

  int* myOwnedElems = new int[numMyElems*2];
  int* ownedSizes = myOwnedElems+numMyElems;
  int numMyOwnedElems = 0;

  for(int i=0; i<numMyElems; ++i) {
    int GID = myElems[i];
    int owner = owner_procs[i];

    if (myPID == owner) {
      ownedSizes[numMyOwnedElems] = sizes[i];
      myOwnedElems[numMyOwnedElems++] = GID;
    }
  }

  Epetra_BlockMap one_to_one_map(-1, numMyOwnedElems, myOwnedElems,
         sizes, usermap.IndexBase(), usermap.Comm());

  delete [] myOwnedElems;
  delete [] owner_procs;
  delete directory;

  return(one_to_one_map);
}
Пример #11
0
TEST_F(HashTableTest, TestForbidRehashing)
{
    Int32HashMap newmap(2, false); // only 3 entries

    newmap.put(1, 10);
    newmap.put(2, 20);
    newmap.put(3, 30);
    capu::status_t returnCode = newmap.put(4, 40); // rehashing is forbidden
    EXPECT_EQ(capu::CAPU_ENO_MEMORY, returnCode);
    EXPECT_EQ(static_cast<capu::uint32_t>(3), newmap.count());

    newmap.remove(3);
    returnCode = newmap.put(4, 40);
    EXPECT_EQ(capu::CAPU_OK, returnCode);
    EXPECT_EQ(static_cast<capu::uint32_t>(3), newmap.count());
}
Пример #12
0
TEST_F(HashTableTest, TestRehasing)
{
    Int32HashMap newmap(2, true); // only 3 entries

    newmap.put(1, 10);
    newmap.put(2, 20);
    newmap.put(3, 30);
    capu::status_t returnCode = newmap.put(4, 40); // rehashing will occur
    EXPECT_EQ(capu::CAPU_OK, returnCode);
    EXPECT_EQ(static_cast<capu::uint32_t>(4), newmap.count());

    EXPECT_EQ(10, newmap.at(1));
    EXPECT_EQ(20, newmap.at(2));
    EXPECT_EQ(30, newmap.at(3));
    EXPECT_EQ(40, newmap.at(4));
}
Пример #13
0
Map *
dumbmap(int fd)
{
	Map *dumb;

	extern Mach mi386;
	extern Machdata i386mach;

	dumb = newmap(0, 1);
	setmap(dumb, fd, 0, 0xffffffff, 0, "data");
	if (!mach) 			/* default machine = 386 */
		mach = &mi386;
	if (!machdata)
		machdata = &i386mach;
	return dumb;
}
Пример #14
0
Map*
loadmap(Map *map, int fd, Fhdr *fp)
{
	map = newmap(map, 2);
	if (map == 0)
		return 0;

	map->seg[0].b = fp->txtaddr;
	map->seg[0].e = fp->txtaddr+fp->txtsz;
	map->seg[0].f = fp->txtoff;
	map->seg[0].fd = fd;
	map->seg[0].inuse = 1;
	map->seg[0].name = "text";
	map->seg[1].b = fp->dataddr;
	map->seg[1].e = fp->dataddr+fp->datsz;
	map->seg[1].f = fp->datoff;
	map->seg[1].fd = fd;
	map->seg[1].inuse = 1;
	map->seg[1].name = "data";
	return map;
}
Пример #15
0
Map*
attachproc(int id, Fhdr *fp)
{
	Thread *t;
	Map *map;

	if((t = idtotable(id)) == nil)
		return nil;
	if(t->map)
		return t->map;
	map = newmap(0, 4);
	if(!map)
		return nil;
	map->pid = -((t-thr) + 1);
	if(mach->regsize)
		setmap(map, -1, 0, mach->regsize, 0, "regs", machregrw);
	setmap(map, -1, fp->txtaddr, fp->txtaddr+fp->txtsz, fp->txtaddr, "*text", machsegrw);
	setmap(map, -1, fp->dataddr, mach->utop, fp->dataddr, "*data", machsegrw);
	t->map = map;
	return map;
}
Пример #16
0
Map Flatten( Map map )
{
	Map newmap(map);
	int bounds[8][2] = {
		{  1,  0 },
		{  1,  1 },
		{  0,  1 },
		{ -1,  1 },
		{ -1,  0 },
		{ -1, -1 },
		{  0, -1 },
		{  1, -1 }
	};
	for( int x = 0; x < map.Width(); x++ )
	for( int y = 0; y < map.Height(); y++ )
	{
		int nb=0;
		for( int i = 0; i < 8; i++ ) nb += (map.GetScroll(x + bounds[i][0], y + bounds[i][1]) == Map::BLOCK_FREE ? 0 : 1);
		if( nb == 8 ) newmap.Set(x, y, Map::BLOCK_FREE);
	}
	return newmap;
}
Пример #17
0
Map Decorate( Map map )
{
	Map newmap(map);
	int bounds[4][2] = {
		{ 1, 0 },
		{ -1, 0 },
		{ 0, 1 },
		{ 0, -1 }
	};
	for( int x = 0; x < map.Width(); x++ )
	for( int y = 0; y < map.Height(); y++ )
	{
		int hnb=0,vnb=0;
		for( int i = 0; i < 2; i++ )
			hnb += (map.GetScroll( x + bounds[i][0], y + bounds[i][1] ) == Map::BLOCK_FREE ? 0 : 1);
		for( int i = 2; i < 4; i++ )
			vnb += (map.GetScroll( x + bounds[i][0], y + bounds[i][1] ) == Map::BLOCK_FREE ? 0 : 1);
		if( (hnb - vnb == 0 || hnb + vnb == 1 ) && map.Get( x, y ) != Map::BLOCK_FREE ) newmap.Set(x, y, 2);
	}
	return newmap;

}
Пример #18
0
void
mapfil(ino_t inode, off_t size, uint8_t *addr)
{
  newmap(inode, size, addr);      /* Tell the Workfile system about this file */

/* If we can defer reading the file, do so */

  if (ptrpos == lintot + 1 && fmode & 010000 && !deferd)
  {
    dcount = 0;                    /* No lines read in from file */
    dfmode = fmode;                /* Remember mode at map time */
    defend = addr + size;          /* Remember file size */
    defpos = dfaddr = addr;        /* Remember file start & current addresses */
    deferd = true;                 /* Tell the world */
    printf("%lld bytes mapped.\r\n", (long long int)size); /* Tell the user */
    return;
  }                                /* if(ptrpos==lintot+1&&fmode&010000&&... */

  lngwrn = true;                   /* Not memrec */
  fileio = false;                  /* File already mmap'd */
  count = 0;                       /* No lines read yet */
  state = 0;                       /* Normal state initially */
  xxmode = fmode;                  /* Use current mode */
  xxprev = prev;                   /* prev contains last line on exit */
  xxprev->bcurs = 0;               /* Cursor at column 1 on exit */
  bytes = size;                    /* Entire file in memory */
  prvpos = bufpos = addr;          /* Data starts here */
  bufend = addr + bytes;           /* Data ends here */
  for (;;)                         /* Loop on lines */
  {
    if (cntrlc && ctlcak())      /* user typed a ^C & confirmed (or macro &c) */
      break;
    if (prclin())                  /* Eof */
      break;
    endLin();
  }                                /* for(;;) */
  printf("%ld lines read.\r\n", count);
}                                  /* void mapfil(ino_t inode,off_t size) */
Пример #19
0
// FIXME long long
Epetra_Map
Epetra_Util::Create_Root_Map(const Epetra_Map& usermap,
         int root)
{
  int numProc = usermap.Comm().NumProc();
  if (numProc==1) {
    Epetra_Map newmap(usermap);
    return(newmap);
  }

  const Epetra_Comm & comm = usermap.Comm();
  bool isRoot = usermap.Comm().MyPID()==root;

  //if usermap is already completely owned by root then we'll just return a copy of it.
  int quickreturn = 0;
  int globalquickreturn = 0;

  if (isRoot) {
    if (usermap.NumMyElements()==usermap.NumGlobalElements64()) quickreturn = 1;
  }
  else {
    if (usermap.NumMyElements()==0) quickreturn = 1;
  }
  usermap.Comm().MinAll(&quickreturn, &globalquickreturn, 1);
  
  if (globalquickreturn==1) {
    Epetra_Map newmap(usermap);
    return(newmap);
  }
  
  // Linear map: Simple case, just put all GIDs linearly on root processor
  if (usermap.LinearMap() && root!=-1) {
    int numMyElements = 0;
    if (isRoot) numMyElements = usermap.MaxAllGID64()+1; // FIXME long long
    Epetra_Map newmap(-1, numMyElements, usermap.IndexBase(), comm);
    return(newmap);
  }

  if (!usermap.UniqueGIDs()) 
    throw usermap.ReportError("usermap must have unique GIDs",-1);

  // General map

  // Build IntVector of the GIDs, then ship them to root processor
  int numMyElements = usermap.NumMyElements();
  Epetra_Map allGidsMap(-1, numMyElements, 0, comm);
  Epetra_IntVector allGids(allGidsMap);
  for (int i=0; i<numMyElements; i++) allGids[i] = usermap.GID64(i);
  
  int numGlobalElements = usermap.NumGlobalElements64();
  if (root!=-1) {
    int n1 = 0; if (isRoot) n1 = numGlobalElements;
    Epetra_Map allGidsOnRootMap(-1, n1, 0, comm);
    Epetra_Import importer(allGidsOnRootMap, allGidsMap);
    Epetra_IntVector allGidsOnRoot(allGidsOnRootMap);
    allGidsOnRoot.Import(allGids, importer, Insert);
    
    Epetra_Map rootMap(-1, allGidsOnRoot.MyLength(), allGidsOnRoot.Values(), usermap.IndexBase(), comm);
    return(rootMap);
  }
  else {
    int n1 = numGlobalElements;
    Epetra_LocalMap allGidsOnRootMap(n1, 0, comm);
    Epetra_Import importer(allGidsOnRootMap, allGidsMap);
    Epetra_IntVector allGidsOnRoot(allGidsOnRootMap);
    allGidsOnRoot.Import(allGids, importer, Insert);
    
    Epetra_Map rootMap(-1, allGidsOnRoot.MyLength(), allGidsOnRoot.Values(), usermap.IndexBase(), comm);

    return(rootMap);
  }
}
Пример #20
0
void
readtext(char *s)
{
	Dir *d;
	Lsym *l;
	Value *v;
	Symbol sym;
	ulong length;
	extern Machdata mipsmach;

	if(mtype != 0){
		symmap = newmap(0, 1);
		if(symmap == 0)
			print("%s: (error) loadmap: cannot make symbol map\n", argv0);
		length = 1<<24;
		d = dirfstat(text);
		if(d != nil) {
			length = d->length;
			free(d);
		}
		setmap(symmap, text, 0, length, 0, "binary");
		free(d);
		return;
	}

	machdata = &mipsmach;

	if(!crackhdr(text, &fhdr)) {
		print("can't decode file header\n");
		return;
	}

	symmap = loadmap(0, text, &fhdr);
	if(symmap == 0)
		print("%s: (error) loadmap: cannot make symbol map\n", argv0);

	if(syminit(text, &fhdr) < 0) {
		print("%s: (error) syminit: %r\n", argv0);
		return;
	}
	print("%s:%s\n\n", s, fhdr.name);

	if(mach->sbreg && lookup(0, mach->sbreg, &sym)) {
		mach->sb = sym.value;
		l = enter("SB", Tid);
		l->v->vstore.fmt = 'X';
		l->v->vstore.u0.sival = mach->sb;
		l->v->type = TINT;
		l->v->set = 1;
	}

	l = mkvar("objtype");
	v = l->v;
	v->vstore.fmt = 's';
	v->set = 1;
	v->vstore.u0.sstring = strnode(mach->name);
	v->type = TSTRING;

	l = mkvar("textfile");
	v = l->v;
	v->vstore.fmt = 's';
	v->set = 1;
	v->vstore.u0.sstring = strnode(s);
	v->type = TSTRING;

	machbytype(fhdr.type);
	varreg();
}
Пример #21
0
int setoptions(Options *options, int argc, char **argv)
{
    opterr = 0;     /* we will print our own error messages */
    int option;
    while ((option = getopt(argc, argv, ":" OPTSTRING)) != -1) {
        switch(option) {
        case '1':
            options->displaymode = DISPLAY_ONE_PER_LINE;
            break;
        case 'A':
            /* maybe print ACLs?  or -a without "." and ".."? */
            break;
        case 'a':
            options->all = true;
            break;
        case 'B':
            options->bytes = true;
            break;
        case 'b':
            /* GNU ls uses this for ESCAPE_C, but we use -e = escape */
            options->bytes = true;
            break;
        case 'C':
            options->displaymode = DISPLAY_IN_COLUMNS;
            break;
        case 'c':
            options->timetype = TIME_CTIME;
            /* this interacts with other options see below */
            break;
        case 'D':
            options->dirsonly = true;
            break;
        case 'd':
            options->directory = true;
            break;
        case 'E':
            options->escape = ESCAPE_NONE;
            break;
        case 'e':
            options->escape = ESCAPE_C;
            break;
        case 'F':
            options->flags = FLAGS_NORMAL;
            break;
        case 'f':
            options->compare = NULL;
            break;
        case 'G':
            /* for compatibility with FreeBSD */
            options->color = true;
            break;
        case 'g':
            /* hopefully saner than legacy ls */
            options->group = true;
            break;
        case 'H':
            options->followdirlinkargs = ON;
            break;
        case 'I':
            options->timeformat = "%Y-%m-%d %H:%M:%S";
            break;
        case 'i':
            options->inode = true;
            break;
        case 'K':
            /* K = "kolor", somewhat mnemonic and unused in GNU ls */
            options->color = true;
            break;
        case 'k':
            options->blocksize = 1024;
            break;
        case 'L':
            options->targetinfo = ON;
            break;
        case 'l':
            options->longformat = true;
            options->modes = true;
            options->linkcount = true;
            options->owner = true;
            options->group = true;
            options->bytes = true;
            options->datetime = true;
            options->showlink = true;
            options->displaymode = DISPLAY_ONE_PER_LINE;
            options->dirtotals = true;
            break;
        case 'M':
            /* might change this to blocksize=1048576 later */
            options->modes = true;
            break;
        case 'm':
            /* conflicts with legacy ls "streams" mode */
            options->modes = true;
            break;
        case 'N':
            options->linkcount = true;
            break;
        case 'n':
            options->numeric = true;
            break;
        case 'O':
            options->flags = FLAGS_OLD;
            break;
        case 'o':
            options->owner = true;
            break;
        case 'P':
            options->targetinfo = OFF;
            break;
        case 'p':
            options->perms = true;
            break;
        case 'q':
            options->escape = ESCAPE_QUESTION;
            break;
        case 'R':
            options->recursive = true;
            break;
        case 'r':
            options->reverse = true;
            break;
        case 'S':
            options->sorttype = SORT_BY_SIZE;
            break;
        case 's':
            options->size = true;
            options->dirtotals = true;
            break;
        case 'T':
            options->datetime = true;
            break;
        case 't':
            options->sorttype = SORT_BY_TIME;
            break;
        case 'U':
            options->sorttype = SORT_UNSORTED;
            break;
        case 'u':
            options->timetype = TIME_ATIME;
            /* this interacts with other options see below */
            break;
        case 'V':
            options->showlinks = true;
            break;
        case 'v':
            options->sorttype = SORT_BY_VERSION;
            break;
        case 'x':
            options->displaymode = DISPLAY_IN_ROWS;
            break;
        case ':':
            error("Missing argument to -%c\n", optopt);
            usage();
            return -1;
        case '?':
            error("Unknown option -%c\n", optopt);
            usage();
            return -1;
        default:
            usage();
            return -1;
        }
    }

    /* compatibility: -c = -ct, -u = -ut (unless -T or -l) */
    if (options->compatible &&
       !options->datetime &&
        options->timetype != TIME_MTIME) {
        options->sorttype = SORT_BY_TIME;
    }

    switch (options->sorttype) {
    case SORT_BY_NAME:
        options->compare = &comparebyname;
        break;
    case SORT_BY_TIME:
        /* XXX make this cleaner */
        switch (options->timetype) {
        case TIME_MTIME:
            options->compare = &comparebymtime;
            break;
        case TIME_ATIME:
            options->compare = &comparebyatime;
            break;
        case TIME_CTIME:
            options->compare = &comparebyctime;
            break;
        default:
            errorf("Unknown time type\n");
            options->compare = &comparebyname;
            break;
        }
        break;
    case SORT_BY_SIZE:
        /* neither POSIX nor GNU seem to define "size"
           but based on experiments, it seems to be the st_size field */
        options->compare = &comparebysize;
        break;
    case SORT_BY_VERSION:
        options->compare = &comparebyversion;
        break;
    case SORT_UNSORTED:
        options->compare = NULL;
        /* don't reverse output if it's unsorted
         * (as per BSD and GNU) */
        if (options->compare == NULL) {
            options->reverse = 0;
        }
        break;
    }

    /* if -H was not given, set it based on other flags...*/
    if (options->followdirlinkargs == DEFAULT) {
        if (options->targetinfo != DEFAULT) {
            /* -L implies -H, -P implies not -H */
            options->followdirlinkargs = options->targetinfo;
        } else if (options->compatible && (options->flags || options->longformat)) {
            /* -F or -l imply not -H */
            options->followdirlinkargs = OFF;
        } else {
            /* if not -L, -P, -F, or -l, -H defaults to on */
            options->followdirlinkargs = ON;
        }
    }

    if (options->targetinfo == DEFAULT) {
        options->targetinfo = OFF;
    }

    if (options->targetinfo == ON) {
      options->showlink = false;
    }

    if (options->color) {
        Colors *colors = malloc(sizeof(*colors));
        if (!colors) {
            errorf("Out of memory?\n");
            goto error;
        }

        options->color = setupcolors(colors);
        options->colors = colors;
    }

    if (options->datetime && options->timeformat == NULL) {
        options->now = time(NULL);
        if (options->now == -1) {
            errorf("Cannot determine current time\n");
            /* non-fatal */
        }
    }

    if (options->group && !options->numeric) {
        options->groupnames = newmap();
        if (!options->groupnames) {
            errorf("Out of memory?\n");
            goto error;
        }
    }
    if (options->owner && !options->numeric) {
        options->usernames = newmap();
        if (!options->usernames) {
            errorf("Out of memory?\n");
            goto error;
        }
    }

    return optind;

error:
    freeoptions(options);
    return -1;
}