Example #1
0
void to_utf8(const std::string & from, std::string & to, uint32_t codepage) {
	
	iconv_t converter = get_converter(codepage);
	
	const char * inbuf = from.data();
	size_t insize = from.size();
	
	size_t outbase = 0;
	
	if(!insize) {
		to.clear();
		return;
	}
	
	iconv(converter, NULL, NULL, NULL, NULL);
	
	while(insize) {
		
		to.resize(outbase + insize + 4);
		
		char * outbuf = &to[0] + outbase;
		size_t outsize = to.size() - outbase;
		
		size_t ret = iconv(converter, const_cast<char**>(&inbuf), &insize, &outbuf, &outsize);
		if(ret == size_t(-1) && errno != E2BIG) {
			log_error << "iconv error while converting from CP" << codepage << ": " << errno;
			to.clear();
			return;
		}
		
		outbase = to.size() - outsize;
	}
	
	to.resize(outbase);
}
Example #2
0
IconvWrapper::IconvWrapper(const char* sourceEncoding, const char* destEncoding, bool enableSubst)
: conv(get_converter(enableSubst, sourceEncoding, destEncoding))
{
	// These need to be set only after we verify that the source and dest
	// charsets are valid
	toNulLen = nul_size(destEncoding);
	fromNulLen = nul_size(sourceEncoding);
}
Example #3
0
void convert__byte_array(long& java_value, long& cxx_value, const CXXTypeHierarchy cxx_type_hierarchy, const converter_t& converter_type, std::stack<long>& converter_stack)
{
	JNIContext *jni = JNIContext::sharedInstance();

	if (converter_type == CONVERT_TO_JAVA)
	{
		jni->pushLocalFrame();
		cxx_converter item_converter = get_converter(converter_stack);
		std::vector<byte> *cxx_vector = (std::vector<byte> *) cxx_value;
		int count = cxx_vector->size();
		char java_array[count];
		int item_idx = 0;
		for(std::vector<byte>::iterator it = cxx_vector->begin(); it != cxx_vector->end(); ++it)
		{
			byte item = (byte) *it;
			java_array[item_idx++] = item;
		}
		java_value = (long) jni->createByteArray(*java_array, count);
		java_value = (long) jni->popLocalFrame((jobject) java_value);
	}
	else if (converter_type == CONVERT_TO_CXX)
	{
		jni->pushLocalFrame();
		cxx_converter item_converter = get_converter(converter_stack);
		std::vector<byte> *cxx_vector = new std::vector<byte>();
		int count = (int) jni->getArrayLength((jarray) java_value);
		char * java_array = jni->getByteArray((jbyteArray) java_value);
		for (int idx = 0 ; idx < count; idx++)
		{
			char item = (char) java_array[idx];
			cxx_vector->push_back((byte) item);
		}
		cxx_value = (long) cxx_vector;
		jni->popLocalFrame();
	}

	log("convert__byte_array exit");
}
Example #4
0
XlcConv
_XlcOpenConverter(
    XLCd from_lcd,
    const char *from,
    XLCd to_lcd,
    const char *to)
{
    XlcConv conv;
    XrmQuark from_type, to_type;

    from_type = XrmStringToQuark(from);
    to_type = XrmStringToQuark(to);

    if ((conv = get_converter(from_lcd, from_type, to_lcd, to_type)))
	return conv;

    return open_indirect_converter(from_lcd, from, to_lcd, to);
}
Example #5
0
static XlcConv
open_indirect_converter(
    XLCd from_lcd,
    const char *from,
    XLCd to_lcd,
    const char *to)
{
    XlcConv lc_conv, from_conv, to_conv;
    Conv conv;
    XrmQuark from_type, to_type;
    static XrmQuark QChar, QCharSet, QCTCharSet = (XrmQuark) 0;

    if (QCTCharSet == (XrmQuark) 0) {
	QCTCharSet = XrmStringToQuark(XlcNCTCharSet);
	QCharSet = XrmStringToQuark(XlcNCharSet);
	QChar = XrmStringToQuark(XlcNChar);
    }

    from_type = XrmStringToQuark(from);
    to_type = XrmStringToQuark(to);

    if (from_type == QCharSet || from_type == QChar || to_type == QCharSet ||
	to_type == QChar)
	return (XlcConv) NULL;

    lc_conv = (XlcConv) Xmalloc(sizeof(XlcConvRec));
    if (lc_conv == NULL)
	return (XlcConv) NULL;

    lc_conv->methods = &conv_methods;

    lc_conv->state = (XPointer) Xcalloc(1, sizeof(ConvRec));
    if (lc_conv->state == NULL)
	goto err;

    conv = (Conv) lc_conv->state;

    from_conv = get_converter(from_lcd, from_type, from_lcd, QCTCharSet);
    if (from_conv == NULL)
	from_conv = get_converter(from_lcd, from_type, from_lcd, QCharSet);
    if (from_conv == NULL)
	from_conv = get_converter((XLCd)NULL, from_type, (XLCd)NULL, QCharSet);
    if (from_conv == NULL)
	from_conv = get_converter(from_lcd, from_type, from_lcd, QChar);
    if (from_conv == NULL)
	goto err;
    conv->from_conv = from_conv;

    to_conv = get_converter(to_lcd, QCTCharSet, to_lcd, to_type);
    if (to_conv == NULL)
	to_conv = get_converter(to_lcd, QCharSet, to_lcd, to_type);
    if (to_conv == NULL)
	to_conv = get_converter((XLCd) NULL, QCharSet, (XLCd) NULL, to_type);
    if (to_conv == NULL)
	goto err;
    conv->to_conv = to_conv;

    return lc_conv;

err:
    close_indirect_converter(lc_conv);

    return (XlcConv) NULL;
}
Example #6
0
int sep_windowed(sep_image *im,
                 double x, double y, double sig, int subpix, short inflag,
                 double *xout, double *yout, int *niter, short *flag)
{
  PIXTYPE pix, varpix;
  double dx, dy, dx1, dy2, offset, scale, scale2, tmp, dxpos, dypos, weight;
  double maskarea, maskweight, maskdxpos, maskdypos;
  double r, tv, twv, sigtv, totarea, overlap, rpix2, invtwosig2;
  double wpix;
  int i, ix, iy, xmin, xmax, ymin, ymax, sx, sy, status, size, esize, msize;
  long pos;
  short errisarray, errisstd;
  BYTE *datat, *errort, *maskt;
  converter convert, econvert, mconvert;
  double r2, r_in2, r_out2;

  /* input checks */
  if (sig < 0.0)
    return ILLEGAL_APER_PARAMS;
  if (subpix < 0)
    return ILLEGAL_SUBPIX;

  /* initializations */
  size = esize = msize = 0;
  tv = sigtv = 0.0;
  overlap = totarea = maskweight = 0.0;
  datat = maskt = NULL;
  errort = im->noise;
  *flag = 0;
  varpix = 0.0;
  scale = 1.0/subpix;
  scale2 = scale*scale;
  offset = 0.5*(scale-1.0);
  invtwosig2 = 1.0/(2.0*sig*sig);
  errisarray = 0;
  errisstd = 0;

  /* Integration radius */
  r = WINPOS_NSIG*sig;

  /* calculate oversampled annulus */
  r2 = r*r;
  oversamp_ann_circle(r, &r_in2, &r_out2);

  /* get data converter(s) for input array(s) */
  if ((status = get_converter(im->dtype, &convert, &size)))
    return status;
  if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize)))
    return status;

  /* get image noise */
  if (im->noise_type != SEP_NOISE_NONE)
    {
      errisstd = (im->noise_type == SEP_NOISE_STDDEV);
      if (im->noise)
        {
          errisarray = 1;
          if ((status = get_converter(im->ndtype, &econvert, &esize)))
            return status;
        }
      else
        {
          varpix = (errisstd)?  im->noiseval * im->noiseval: im->noiseval;
        }
    }

  /* iteration loop */
  for (i=0; i<WINPOS_NITERMAX; i++)
    {

      /* get extent of box */
      boxextent(x, y, r, r, im->w, im->h,
                &xmin, &xmax, &ymin, &ymax, flag);

      /* TODO: initialize values */
      //mx2ph
      //my2ph
      // esum, emxy, emx2, emy2, mx2, my2, mxy
      tv = twv = sigtv = 0.0;
      overlap = totarea = maskarea = maskweight = 0.0;
      dxpos = dypos = 0.0;
      maskdxpos = maskdypos = 0.0;

      /* loop over rows in the box */
      for (iy=ymin; iy<ymax; iy++)
        {
          /* set pointers to the start of this row */
          pos = (iy % im->h) * im->w + xmin;
          datat = MSVC_VOID_CAST im->data + pos*size;
          if (errisarray)
            errort = MSVC_VOID_CAST im->noise + pos*esize;
          if (im->mask)
            maskt = MSVC_VOID_CAST im->mask + pos*msize;

          /* loop over pixels in this row */
          for (ix=xmin; ix<xmax; ix++)
            {
              dx = ix - x;
              dy = iy - y;
              rpix2 = dx*dx + dy*dy;
              if (rpix2 < r_out2)
                {
                  if (rpix2 > r_in2)  /* might be partially in aperture */
                    {
                      if (subpix == 0)
                        overlap = circoverlap(dx-0.5, dy-0.5, dx+0.5, dy+0.5,
                                              r);
                      else
                        {
                          dx += offset;
                          dy += offset;
                          overlap = 0.0;
                          for (sy=subpix; sy--; dy+=scale)
                            {
                              dx1 = dx;
                              dy2 = dy*dy;
                              for (sx=subpix; sx--; dx1+=scale)
                                if (dx1*dx1 + dy2 < r2)
                                  overlap += scale2;
                            }
                        }
                    }
                  else
                    /* definitely fully in aperture */
                    overlap = 1.0;

                  /* get pixel value and variance value */
                  pix = convert(datat);
                  if (errisarray)
                    {
                      varpix = econvert(errort);
                      if (errisstd)
                        varpix *= varpix;
                    }

                  /* offset of this pixel from center */
                  dx = ix - x; 
                  dy = iy - y;

                  /* weight by gaussian */
                  weight = exp(-rpix2*invtwosig2);

                  if (im->mask && (mconvert(maskt) > im->maskthresh))
                    {
                      *flag |= SEP_APER_HASMASKED;
                      maskarea += overlap;
                      maskweight += overlap * weight;
                      maskdxpos += overlap * weight * dx;
                      maskdypos += overlap * weight * dy;
                    }
                  else
                    {
                      tv += pix * overlap;
                      wpix = pix * overlap * weight;
                      twv += wpix;
                      dxpos += wpix * dx;
                      dypos += wpix * dy;
                    }

                  totarea += overlap;

                } /* closes "if pixel might be within aperture" */

              /* increment pointers by one element */
              datat += size;
              if (errisarray)
                errort += esize;
              maskt += msize;
            } /* closes loop over x */
        } /* closes loop over y */

      /* we're done looping over pixels for this iteration.
       * Our summary statistics are:
       *
       * tv : total value
       * twv : total weighted value
       * dxpos : weighted dx
       * dypos : weighted dy
       */

      /* Correct for masked values: This effectively makes it as if
       * the masked pixels had the value of the average unmasked value
       * in the aperture.
       */
      if (im->mask)
        {
          /* this option will probably not yield accurate values */
          if (inflag & SEP_MASK_IGNORE)
            totarea -= maskarea;
          else
            {
              tmp = tv/(totarea-maskarea); /* avg unmasked pixel value */
              twv += tmp * maskweight;
              dxpos += tmp * maskdxpos;
              dypos += tmp * maskdypos;
            }
        }

      /* update center */
      if (twv>0.0)
        {
          x += (dxpos /= twv) * WINPOS_FAC;
          y += (dypos /= twv) * WINPOS_FAC;
        }
      else
        break;

      /* Stop here if position does not change */
      if (dxpos*dxpos+dypos*dypos < WINPOS_STEPMIN*WINPOS_STEPMIN)
        break;

    } /* closes loop over interations */

  /* assign output results */
  *xout = x;
  *yout = y;
  *niter = i+1;

  return status;
}
Example #7
0
/* calculate Kron radius from pixels within an ellipse. */
int sep_kron_radius(sep_image *im, double x, double y,
                    double cxx, double cyy, double cxy, double r, int id, 
                    double *kronrad, short *flag)
{
  float pix;
  double r1, v1, r2, area, rpix2, dx, dy;
  int ix, iy, xmin, xmax, ymin, ymax, status, size, msize, ssize;
  long pos;
  int ismasked;
  
  BYTE *datat, *maskt, *segt;
  converter convert, mconvert, sconvert;

  r2 = r*r;
  r1 = v1 = 0.0;
  area = 0.0;
  *flag = 0;
  datat = maskt = segt = NULL;
  size = msize = ssize = 0;

  /* get data converter(s) for input array(s) */
  if ((status = get_converter(im->dtype, &convert, &size)))
    return status;
  if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize)))
      return status;
  if (im->segmap && (status = get_converter(im->sdtype, &sconvert, &ssize)))
      return status;

  /* get extent of ellipse in x and y */
  boxextent_ellipse(x, y, cxx, cyy, cxy, r, im->w, im->h,
                    &xmin, &xmax, &ymin, &ymax, flag);

  /* loop over rows in the box */
  for (iy=ymin; iy<ymax; iy++)
    {
      /* set pointers to the start of this row */
      pos = (iy % im->h) * im->w + xmin;
      datat = MSVC_VOID_CAST im->data + pos*size;
      if (im->mask)
        maskt = MSVC_VOID_CAST im->mask + pos*msize;
      if (im->segmap)
        segt = MSVC_VOID_CAST im->segmap + pos*ssize;

      /* loop over pixels in this row */
      for (ix=xmin; ix<xmax; ix++)
        {
          dx = ix - x;
          dy = iy - y;
          rpix2 = cxx*dx*dx + cyy*dy*dy + cxy*dx*dy;
          if (rpix2 <= r2)
            {
              pix = convert(datat);
              ismasked = 0;
              if ((pix < -BIG) || (im->mask && mconvert(maskt) > im->maskthresh))
                ismasked = 1;

              /* Segmentation image:  

    	           If `id` is negative, require segmented pixels within the 
    	           aperture.

    	           If `id` is positive, mask pixels with nonzero segment ids
    	           not equal to `id`.

    	      */ 
    	      if (im->segmap)
      	        {
      	          if (id > 0) 
      	            {
      	              if ((sconvert(segt) > 0.) & (sconvert(segt) != id))
      	                {
      	                  ismasked = 1;
      	                }
      	            } else {
    	              if (sconvert(segt) != -1*id)
    	                {
    	                  ismasked = 1;
    	                }  	            
      	            }
      	        }
                
              if (ismasked > 0)
                {
                  *flag |= SEP_APER_HASMASKED;
                }
              else
                {
                  r1 += sqrt(rpix2)*pix;
                  v1 += pix;
                  area++;
                }
            }

          /* increment pointers by one element */
          datat += size;
          maskt += msize;
          segt += ssize;
        }
    }

  if (area == 0)
    {
      *flag |= SEP_APER_ALLMASKED;
      *kronrad = 0.0;
    }
  else if (r1 <= 0.0 || v1 <= 0.0)
    {
      *flag |= SEP_APER_NONPOSITIVE;
      *kronrad = 0.0;
    }
  else
    {
      *kronrad = r1 / v1;
    }

  return RETURN_OK;
}
Example #8
0
/*
 * This is just different enough from the other aperture functions
 * that it doesn't quite make sense to use aperture.i.
 */
int sep_sum_circann_multi(sep_image *im,
                          double x, double y, double rmax, int n, 
                          int id, 
                          int subpix,
                          short inflag,
                          double *sum, double *sumvar, double *area,
                          double *maskarea, short *flag)
{
  PIXTYPE pix, varpix;
  double dx, dy, dx1, dy2, offset, scale, scale2, tmp, rpix2;
  int ix, iy, xmin, xmax, ymin, ymax, sx, sy, status, size, esize, msize, ssize;
  long pos;
  short errisarray, errisstd;
  BYTE *datat, *errort, *maskt, *segt;
  converter convert, econvert, mconvert, sconvert;
  double rpix, r_out, r_out2, d, prevbinmargin, nextbinmargin, step, stepdens;
  int j, ismasked;

  /* input checks */
  if (rmax < 0.0 || n < 1)
    return ILLEGAL_APER_PARAMS;
  if (subpix < 1)
    return ILLEGAL_SUBPIX;

  /* clear results arrays */
  memset(sum, 0, (size_t)(n*sizeof(double)));
  memset(sumvar, 0, (size_t)(n*sizeof(double)));
  memset(area, 0, (size_t)(n*sizeof(double)));
  if (im->mask)
    memset(maskarea, 0, (size_t)(n*sizeof(double)));

  /* initializations */
  size = esize = msize = 0;
  datat = maskt = segt = NULL;
  errort = im->noise;
  *flag = 0;
  varpix = 0.0;
  scale = 1.0/subpix;
  scale2 = scale*scale;
  offset = 0.5*(scale-1.0);

  r_out = rmax + 1.5; /* margin for interpolation */
  r_out2 = r_out * r_out;
  step = rmax/n;
  stepdens = 1.0/step;
  prevbinmargin = 0.7072;
  nextbinmargin = step - 0.7072;
  j = 0;
  d = 0.;
  ismasked = 0;
  errisarray = 0;
  errisstd = 0;

  /* get data converter(s) for input array(s) */
  if ((status = get_converter(im->dtype, &convert, &size)))
    return status;
  if (im->mask && (status = get_converter(im->mdtype, &mconvert, &msize)))
    return status;
  if (im->segmap && (status = get_converter(im->sdtype, &sconvert, &ssize)))
    return status;

  /* get image noise */
  if (im->noise_type != SEP_NOISE_NONE)
    {
      errisstd = (im->noise_type == SEP_NOISE_STDDEV);
      if (im->noise)
        {
          errisarray = 1;
          if ((status = get_converter(im->ndtype, &econvert, &esize)))
            return status;
        }
      else
        {
          varpix = (errisstd)?  im->noiseval * im->noiseval: im->noiseval;
        }
    }


  /* get extent of box */
  boxextent(x, y, r_out, r_out, im->w, im->h, &xmin, &xmax, &ymin, &ymax,
            flag);

  /* loop over rows in the box */
  for (iy=ymin; iy<ymax; iy++)
    {
      /* set pointers to the start of this row */
      pos = (iy % im->h) * im->w + xmin;
      datat = MSVC_VOID_CAST im->data + pos*size;
      if (errisarray)
        errort = MSVC_VOID_CAST im->noise + pos*esize;
      if (im->mask)
        maskt = MSVC_VOID_CAST im->mask + pos*msize;
      if (im->segmap)
        segt = MSVC_VOID_CAST im->segmap + pos*ssize;

      /* loop over pixels in this row */
      for (ix=xmin; ix<xmax; ix++)
        {
          dx = ix - x;
          dy = iy - y;
          rpix2 = dx*dx + dy*dy;
          if (rpix2 < r_out2)
            {
              /* get pixel values */
              pix = convert(datat);
              if (errisarray)
                {
                  varpix = econvert(errort);
                  if (errisstd)
                    varpix *= varpix;
                }
              
              ismasked = 0;
              if (im->mask)
                {
                  if (mconvert(maskt) > im->maskthresh)
                    {
                      *flag |= SEP_APER_HASMASKED;
                      ismasked = 1;
                    }
                }

              /* Segmentation image:  

    	           If `id` is negative, require segmented pixels within the 
    	           aperture.

    	           If `id` is positive, mask pixels with nonzero segment ids
    	           not equal to `id`.

    	      */ 
    	      if (im->segmap)
      	        {
      	          if (id > 0) 
      	            {
      	              if ((sconvert(segt) > 0.) & (sconvert(segt) != id))
      	                {
                          *flag |= SEP_APER_HASMASKED;
      	                  ismasked = 1;
      	                }
      	            } else {
    	              if (sconvert(segt) != -1*id)
    	                {
                          *flag |= SEP_APER_HASMASKED;
    	                  ismasked = 1;
    	                }  	            
      	            }
      	        }
      	        
              /* check if oversampling is needed (close to bin boundary?) */
              rpix = sqrt(rpix2);
              d = fmod(rpix, step);
              if (d < prevbinmargin || d > nextbinmargin)
                {
                  dx += offset;
                  dy += offset;
                  for (sy=subpix; sy--; dy+=scale)
                    {
                      dx1 = dx;
                      dy2 = dy*dy;
                      for (sx=subpix; sx--; dx1+=scale)
                        {
                          j = (int)(sqrt(dx1*dx1+dy2)*stepdens);
                          if (j < n)
                            {
                              if (ismasked)
                                maskarea[j] += scale2;
                              else
                                {
                                  sum[j] += scale2*pix;
                                  sumvar[j] += scale2*varpix;
                                }
                              area[j] += scale2;
                            }
                        }
                    }
                }
              else
                /* pixel not close to bin boundary */
                {
                  j = (int)(rpix*stepdens);
                  if (j < n)
                    {
                      if (ismasked)
                        maskarea[j] += 1.0;
                      else
                        {
                          sum[j] += pix;
                          sumvar[j] += varpix;
                        }
                      area[j] += 1.0;
                    }
                }
            } /* closes "if pixel might be within aperture" */

          /* increment pointers by one element */
          datat += size;
          if (errisarray)
            errort += esize;
          maskt += msize;
          segt += ssize;
        }
    }


  /* correct for masked values */
  if (im->mask)
    {
      if (inflag & SEP_MASK_IGNORE)
        for (j=n; j--;)
          area[j] -= maskarea[j];
      else
        {
          for (j=n; j--;)
            {
              tmp = area[j] == maskarea[j]? 0.0: area[j]/(area[j]-maskarea[j]);
              sum[j] *= tmp;
              sumvar[j] *= tmp;
            }
        }
    }

  /* add poisson noise, only if gain > 0 */
  if (im->gain > 0.0)
    for (j=n; j--;)
      if (sum[j] > 0.0)
        sumvar[j] += sum[j] / im->gain;

  return status;
}
Example #9
0
void convert__object_array_type(long& java_value, long& cxx_value, const CXXTypeHierarchy cxx_type_hierarchy, const converter_t& converter_type, std::stack<long>& converter_stack)
{
	JNIContext *jni = JNIContext::sharedInstance();

	if (converter_type == CONVERT_TO_JAVA)
	{
		jni->pushLocalFrame();

		cxx_converter item_converter = get_converter(converter_stack);

		std::vector<long> *cxx_vector = (std::vector<long> *) cxx_value;
		int count = cxx_vector->size();

		std::string child_type = jni->getJNIName( std::string("java.lang.Object") );
		CXXTypeHierarchy item_type;
		item_type.type_name = child_type;
		std::vector<CXXTypeHierarchy> child_types = cxx_type_hierarchy.child_types;
		if (child_types.size() > 0)
		{
			item_type = child_types.at(0);
			child_type = jni->getJNIName( item_type.type_name );
		}

		java_value = (long) jni->createObjectArray(count, jni->getClassRef( child_type.c_str() ));

		for(std::vector<long>::iterator it = cxx_vector->begin(); it != cxx_vector->end(); ++it)
		{
			long cxx_item_ptr = (long) *it;
			long java_item_ptr = 0;
			int item_idx = it - cxx_vector->begin();
			item_converter(java_item_ptr, cxx_item_ptr, item_type, converter_type, converter_stack);
			jni->setObjectArrayElement((jobjectArray) java_value, item_idx, (jobject) java_item_ptr);
		}

		java_value = (long) jni->popLocalFrame((jobject) java_value);
	}
	else if (converter_type == CONVERT_TO_CXX)
	{
		jni->pushLocalFrame();

		std::string child_type = jni->getJNIName( std::string("java.lang.Object") );
		CXXTypeHierarchy item_type;
		item_type.type_name = child_type;
		std::vector<CXXTypeHierarchy> child_types = cxx_type_hierarchy.child_types;
		if (child_types.size() > 0)
		{
			item_type = child_types.at(0);
			child_type = jni->getJNIName( item_type.type_name );
		}

		cxx_converter item_converter = get_converter(converter_stack);
		std::vector<long> *cxx_vector = (std::vector<long> *) cxx_value;
		int size = (int) jni->getArrayLength((jobjectArray) java_value);
		for (int idx = 0 ; idx < size; idx++)
		{
			long java_item_ptr = (long) jni->getObjectArrayElement((jobjectArray) java_value, idx);
			long cxx_item_ptr = 0;
			item_converter(java_item_ptr, cxx_item_ptr, item_type, converter_type, converter_stack);
			cxx_vector->push_back(cxx_item_ptr);
		}

		jni->popLocalFrame();
	}
}
Example #10
0
File: man.c Project: haggaie/man
/*
 * Create command to format FILE, in the directory PATH/manX
 */
static char *
make_roff_command (const char *path, const char *file) {
     FILE *fp;
     static char buf [BUFSIZE];
     char line [BUFSIZE], bufh [BUFSIZE], buft [BUFSIZE];
     int status, ll;
     char *cp, *fgr, *pl;
     char *command = "";
     const char *expander;
     const char *converter;

     /* if window size differs much from 80, try to adapt */
     /* (but write only standard formatted files to the cat directory,
	see can_use_cache) */
     ll = setll();
     pl = setpl();
     if (ll && debug)
	  gripe (NO_CAT_FOR_NONSTD_LL);

     expander = get_expander (file);
     converter = get_converter (path);

     /* head */
     bufh[0] = 0;
     if (ll || pl) {
	  /* some versions of echo do not accept the -e flag,
	     so we just use two echo calls when needed */
	  strcat(bufh, "(");
	  if (ll) {
	       /*
		* We should set line length and title line length.
		* However, a .lt command here fails, only
		*  .ev 1; .lt ...; .ev helps for my version of groff.
		* The LL assignment is needed by the mandoc macros.
		*/
	       sprintf(eos(bufh), "echo \".ll %d.%di\"; ", ll/10, ll%10);
	       sprintf(eos(bufh), "echo \".nr LL %d.%di\"; ", ll/10, ll%10);
#if 0
	       sprintf(eos(bufh), "echo \".lt %d.%di\"; ", ll/10, ll%10);
#endif
	  }
	  if (pl)
	       sprintf(eos(bufh), "echo \".pl %.128s\"; ", pl);
     }

     /* tail */
     buft[0] = 0;
     if (ll || pl) {
	  if (pl && !strcmp(pl, VERY_LONG_PAGE))
	      /* At end of the nroff source, set the page length to
		 the current position plus 10 lines.  This plus setpl()
		 gives us a single page that just contains the whole
		 man page. (William Webber, [email protected]) */
	      strcat(buft, "; echo \".\\\\\\\"\"; echo \".pl \\n(nlu+10\"");
#if 0
	      /* In case this doesnt work for some reason,
		 michaelkjohnson suggests: I've got a simple
		 awk invocation that I throw into the pipeline: */

		 awk 'BEGIN {RS="\n\n\n\n*"} /.*/ {print}'
#endif
	  strcat(buft, ")");
     }

     if (expander && *expander) {
	  if (converter && *converter)
	     command = my_xsprintf("%s%s '%S' | %s%s",
				   bufh, expander, file, converter, buft);
	  else
	     command = my_xsprintf("%s%s '%S'%s",
				   bufh, expander, file, buft);
     } else if (ll || pl) {
	  const char *cat = getval("CAT");
	  if (!cat || !*cat)
		  cat = "cat";

	  if (converter && *converter)
	      command = my_xsprintf("%s%s '%S' | %s%s",
				    bufh, cat, file, converter, buft);
	  else
	      command = my_xsprintf("%s%s '%S'%s",
				    bufh, cat, file, buft);
     }

     if (strlen(command) >= sizeof(buf))
	  exit(1);
     strcpy(buf, command);

     if (roff_directive != NULL) {
	  if (debug)
	       gripe (ROFF_FROM_COMMAND_LINE);

	  status = parse_roff_directive (roff_directive, file,
					 buf, sizeof(buf));

	  if (status == 0)
	       return buf;

	  if (status == -1)
	       gripe (ROFF_CMD_FROM_COMMANDLINE_ERROR);
     }

     if (expander && *expander) {
	  char *cmd = my_xsprintf ("%s %S", expander, file);
	  fp = my_popen (cmd, "r");
	  if (fp == NULL) {
	       perror("popen");
	       gripe (EXPANSION_FAILED, cmd);
	       return (NULL);
	  }
	  fgr = fgets (line, sizeof(line), fp);
	  pclose (fp);
     } else {
	  fp = fopen (file, "r");
	  if (fp == NULL) {
	       perror("fopen");
	       gripe (OPEN_ERROR, file);
	       return (NULL);
	  }
	  fgr = fgets (line, sizeof(line), fp);
	  fclose (fp);
     }

     if (fgr == NULL) {
	  perror("fgets");
	  gripe (READ_ERROR, file);
	  return (NULL);
     }

     cp = &line[0];
     if (*cp++ == '\'' && *cp++ == '\\' && *cp++ == '"' && *cp++ == ' ') {
	  if (debug)
	       gripe (ROFF_FROM_FILE, file);

	  status = parse_roff_directive (cp, file, buf, sizeof(buf));

	  if (status == 0)
	       return buf;

	  if (status == -1)
	       gripe (ROFF_CMD_FROM_FILE_ERROR, file);
     }

     if ((cp = getenv ("MANROFFSEQ")) != NULL) {
	  if (debug)
	       gripe (ROFF_FROM_ENV);

	  status = parse_roff_directive (cp, file, buf, sizeof(buf));

	  if (status == 0)
	       return buf;

	  if (status == -1)
	       gripe (MANROFFSEQ_ERROR);
     }

     if (debug)
	  gripe (USING_DEFAULT);

     (void) parse_roff_directive ("t", file, buf, sizeof(buf));

     return buf;
}