(char *) &d[1] - (char *) data);
(char *) d - (char *) data);   od = (newsp + ((char *) d - (char *) data)); if ((void *) argv[0] == d)  memset (od, 0, sizeof *od); else  *od = *d;
init (int *data, int retaddr){  int argc = *data;  char **argv = (void *) (data + 1);  char **envp = &argv[argc + 1];  struct hurd_startup_data *d;  __environ = envp;  while (*envp)    ++envp;  d = (void *) ++envp;  /* The user might have defined a value for this, to get more variables.     Otherwise it will be zero on startup.  We must make sure it is set     properly before before cthreads initialization, so cthreads can know     how much space to leave for thread variables.  */  if (__hurd_threadvar_max < _HURD_THREADVAR_MAX)    __hurd_threadvar_max = _HURD_THREADVAR_MAX;  if (_cthread_init_routine)    {      /* Initialize cthreads, which will allocate us a new stack to run on.  */      void *newsp = (*_cthread_init_routine) ();      /* Copy the argdata from the old stack to the new one.  */      newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data,		      (char *) &d[1] - (char *) data);      data = newsp;    }  /* Call `init1' (above) with the user code as the return address,     and the argument data immediately above that on the stack.  */  *--data = retaddr;  asm volatile ("movl %0, %%esp; jmp %*%1" : : "g" (data), "r" (&init1));}  