Exemplo n.º 1
0
Arquivo: view.c Projeto: bytbox/iv
/* inserts a character at the cursor */
void insertc(view_t *view,unsigned char c) {
    /* check readonly */
    if(view->buffer->readonly)
        error_throw(ERR_READONLY);
    /* check valid character */
    if((char)c<0) return;
    char *line=view->buffer->lines[view->cursor_line];
    /* make sure the line is long enough */
    view->buffer->lines[view->cursor_line]=strexpand(line,strlen(line)+2);
    line=view->buffer->lines[view->cursor_line];
    /* make a copy of the line */
    char *tln=malloc(strlen(line)+2);
    char *ln=tln;
    sprintf(ln,"%s",line);
    /* put the line back together */
    /* copy the first part back */
    line[0]='\0';
    strncat(line,ln,view->cursor_x);
    /* copy the character */
    line[strlen(line)+1]='\0';
    line[strlen(line)]=c;
    /* copy the second part back */
    ln+=view->cursor_x;
    strcat(line,ln);
    free(tln); /* free temporary buffer */
    /* advance the cursor */
    view->pref_x++;
    clean_cursor_x(view);
    /* we've been modified */
    view->buffer->modified=1;
}
Exemplo n.º 2
0
SC_FUNC int phopt_init(void)
{
  int number, i, len;
  char str[160];

  /* count number of sequences */
  for (number=0; sequences_cmp[number].find!=NULL; number++)
    /* nothing */;
  number++;             /* include an item for the NULL terminator */

  if ((sequences=(SEQUENCE*)malloc(number * sizeof(SEQUENCE)))==NULL)
    return FALSE;

  /* pre-initialize all to NULL (in case of failure) */
  for (i=0; i<number; i++) {
    sequences[i].find=NULL;
    sequences[i].replace=NULL;
    sequences[i].opc=0;
    sequences[i].arg=0;
  } /* for */

  /* expand all strings */
  for (i=0; i<number-1; i++) {
    len = strexpand(str,(unsigned char*)sequences_cmp[i].find,sizeof str,SCPACK_TABLE);
    assert(len<=sizeof str);
    assert(len==(int)strlen(str)+1);
    sequences[i].find=(char*)malloc(len);
    if (sequences[i].find!=NULL)
      strcpy((char*)sequences[i].find,str);
    len = strexpand(str,(unsigned char*)sequences_cmp[i].replace,sizeof str,SCPACK_TABLE);
    assert(len<=sizeof str);
    assert(len==(int)strlen(str)+1);
    sequences[i].replace=(char*)malloc(len);
    if (sequences[i].replace!=NULL)
      strcpy((char*)sequences[i].replace,str);
    sequences[i].opc=sequences_cmp[i].opc;
    sequences[i].arg=sequences_cmp[i].arg;
    if (sequences[i].find==NULL || sequences[i].replace==NULL)
      return phopt_cleanup();
  } /* for */

  return TRUE;
}
Exemplo n.º 3
0
int main (int argc, char **argv)
{
  int i;
  char str[128];

  for (i=0; i<58; i++) {
    strexpand(str, errmsg[i], sizeof str, SCPACK_TABLE);
    printf("%s", str);
  } /* for */
  return 0;
}
Exemplo n.º 4
0
Arquivo: view.c Projeto: bytbox/iv
/* delete a character at the cursor */
void deletec(view_t *view) {
    /* exit if there's nothing to delete */
    if(view->cursor_x==0 && view->cursor_line==0)
        return;
    /* clean up our position */
    clean_cursor_x(view);
    clean_pref_x(view);
    /* should we merge lines? */
    if(view->cursor_x==0) {
        /* merge lines */
        char *line=view->buffer->lines[view->cursor_line];
        view->buffer->lines[view->cursor_line-1]=
            strexpand(view->buffer->lines[view->cursor_line-1],
                      strlen(view->buffer->lines[view->cursor_line-1])+
                      strlen(line));
        view->pref_x=strlen(view->buffer->lines[view->cursor_line-1]);
        strcat(view->buffer->lines[view->cursor_line-1],line);
        free(line); /* free the line */
        /* reduce line count */
        view->buffer->line_count--;
        /* scroll all future lines up */
        int i;
        for(i=view->cursor_line;i<view->buffer->line_count;i++)
            view->buffer->lines[i]=view->buffer->lines[i+1];
        /* move the cursor */
        cursor_up(view);
        return;
    }
    /* no line merging to be done */
    /* get the line */
    char *line=view->buffer->lines[view->cursor_line];
        /* make a copy of the line */
    char *tln=malloc(strlen(line)+2);
    char *ln=tln;
    sprintf(ln,"%s",line);
    /* copy the first part back */
    line[0]='\0';
    strncat(line,ln,view->cursor_x-1);
    /* copy the second part back */
    ln+=view->cursor_x;
    strcat(line,ln);
    free(tln); /* free temporary buffer */
    /* retreat the cursor */
    view->pref_x--;
    view->cursor_x--;
    /* we've been modified */
    view->buffer->modified=1;
}
Exemplo n.º 5
0
int main(int argc, char **argv)
{
  while(--argc > 0)
  {
    char *s= strexpand(*++argv, table);

    if(s)
    {
      puts(s);
      free(s);
    }
    else printf("strexpand(\"%s\") failed.\n",*argv);
  }

  return 0;
}
Exemplo n.º 6
0
int gen_autodoc(FILE *fp, int cols, int tabsize, int flags, char **body_macros)
{
  int err= 0;

  char *fun, *sec, *text;

  for(fun= stepfun(0); fun && (err==0); fun= stepfun(1))
  {
    if(flags & ADOC_FORM_FEEDS)
      fputc('\f',fp);

    fprintf(fp,"%s%*s\n\n",fun,(int)(cols-strlen(fun)),fun);

    for(sec= stepsec(0); sec && (err==0); sec= stepsec(1))
    {
      /* indent the section heading with 3 spaces */
      if(*sec)
        fprintf(fp,"   %s\n",sec);

      if( (text= getsec(sec)) )
      {
        if(text && *text)
        {
          char *x= strexpand(text, body_macros);

          if(x)
          {
            if(tabsize > 0)
              fexpand(fp,tabsize,x);

            else
              fputs(x,fp);

            free(x);
          }
          else err= __LINE__;
        }

        fputc('\n',fp);
      }
    }
  }

  return err;
}
Exemplo n.º 7
0
/*  error
 *
 *  Outputs an error message (note: msg is passed optionally).
 *  If an error is found, the variable "errflag" is set and subsequent
 *  errors are ignored until lex() finds a semicolon or a keyword
 *  (lex() resets "errflag" in that case).
 *
 *  Global references: inpfname   (reffered to only)
 *                     fline      (reffered to only)
 *                     fcurrent   (reffered to only)
 *                     errflag    (altered)
 */
SC_FUNC int error(long number,...)
{
static char *prefix[3]={ "error", "fatal error", "warning" };
static int lastline,errorcount;
static short lastfile;
  char *msg,*pre,*filename;
  va_list argptr;
  char string[256];
  int notice;

  /* split the error field between the real error/warning number and an optional
   * "notice" number
   */
  notice=number >> (sizeof(long)*4);
  number&=((unsigned long)~0) >> (sizeof(long)*4);
  assert(number>0 && number<300);

  /* errflag is reset on each semicolon.
   * In a two-pass compiler, an error should not be reported twice. Therefore
   * the error reporting is enabled only in the second pass (and only when
   * actually producing output). Fatal errors may never be ignored.
   */
  if ((errflag || sc_status!=statWRITE) && (number<100 || number>=200))
    return 0;

  /* also check for disabled warnings */
  if (number>=200) {
    int index=(number-200)/8;
    int mask=1 << ((number-200)%8);
    if ((warndisable[index] & mask)!=0) {
      errline=-1;
      errfile=-1;
      return 0;
    } /* if */
  } /* if */

  if (number<100){
    assert(number>0 && number<sizearray(errmsg));
    msg=errmsg[number];
    pre=prefix[0];
    errflag=TRUE;       /* set errflag (skip rest of erroneous expression) */
    errnum++;
  } else if (number<200) {
    assert((number-100)>=0 && (number-100)<sizearray(fatalmsg));
    msg=fatalmsg[number-100];
    pre=prefix[1];
    errnum++;           /* a fatal error also counts as an error */
  } else {
    assert((number-200)>=0 && (number-200)<sizearray(warnmsg));
    msg=warnmsg[number-200];
    pre=prefix[2];
    warnnum++;
  } /* if */

  strexpand(string,(unsigned char *)msg,sizeof string-2,SCPACK_TABLE);
  if (notice>0) {
    int len;
    assert(notice<sizearray(noticemsg));
    strcat(string,"; ");
    len=strlen(string);
    strexpand(string+len,(unsigned char *)noticemsg[notice],sizeof string-len-1,SCPACK_TABLE);
  } /* if */
  strcat(string,"\n");

  if (errline>0)
    errstart=errline;           /* forced error position, set single line destination */
  else
    errline=fline;              /* normal error, errstart may (or may not) have been marked, endpoint is current line */
  if (errstart>errline)
    errstart=errline;           /* special case: error found at end of included file */
  if (errfile>=0) {
    filename=get_inputfile(errfile);/* forced filename */
  } else {
    filename=inpfname;          /* current file */
    if (filename==NULL || strlen(filename)==0)
      filename=get_sourcefile(0);
    if (filename==NULL || strlen(filename)==0)
      filename="(none)";
  } /* if */
  assert(filename!=NULL);

  va_start(argptr,number);
  if (strlen(errfname)==0) {
    int start= (errstart==errline) ? -1 : errstart;
    if (pc_error((int)number,string,filename,start,errline,argptr)) {
      if (outf!=NULL) {
        pc_closeasm(outf,TRUE);
        outf=NULL;
      } /* if */
      longjmp(errbuf,3);        /* user abort */
    } /* if */
  } else {
    FILE *fp=fopen(errfname,"a");
    if (fp!=NULL) {
      if (errstart>=0 && errstart!=errline)
        fprintf(fp,"%s(%d -- %d) : %s %03d: ",filename,errstart,errline,pre,(int)number);
      else
        fprintf(fp,"%s(%d) : %s %03d: ",filename,errline,pre,(int)number);
      vfprintf(fp,string,argptr);
      fclose(fp);
    } /* if */
  } /* if */
  va_end(argptr);

  if (number>=100 && number<200 || errnum>25){
    if (strlen(errfname)==0) {
      va_start(argptr,number);
      pc_error(0,"\nCompilation aborted.",NULL,0,0,argptr);
      va_end(argptr);
    } /* if */
    if (outf!=NULL) {
      pc_closeasm(outf,TRUE);
      outf=NULL;
    } /* if */
    longjmp(errbuf,2);          /* fatal error, quit */
  } /* if */

  errline=-1;
  errfile=-1;
  /* check whether we are seeing many errors on the same line */
  if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile)
    errorcount=0;
  lastline=fline;
  lastfile=fcurrent;
  if (number<200)
    errorcount++;
  if (errorcount>=3)
    error(107);         /* too many error/warning messages on one line */

  return 0;
}
Exemplo n.º 8
0
int gen_texinfo_header(FILE *fp, char *fname, char **header_macros)
{
  int err= 0;

  char *default_header=
    "\\input texinfo  @c -*-texinfo-*-\n"
    "@comment %%**start of header\n"
    "@setfilename PROJECT.guide\n"
    "@settitle Autodocs for @code{PROJECT}\n"
    "@paragraphindent 0\n"
    "@iftex\n"
    "@afourpaper\n"
    "@finalout\n"
    "@setchapternewpage on\n"  /* odd */
    "@end iftex\n"
    "@comment %%**end of header\n\n"
    "@ifinfo\n"
    "@node Top\n"
    "@top\n"
    "This document describes @code{PROJECT} version REVISION.\n\n"
    "@noindent Copyright @copyright{} COPYRIGHT\n"
    "@end ifinfo\n\n"
    "@titlepage\n"
    "@title PROJECT\n"
    "@subtitle Documentation taken from source code\n"
    "@subtitle Edition EDITION for Version REVISION\n"
    "@subtitle @today\n"
    "@author AUTHOR\n\n"
    "@page\n"
    "@vskip 0pt plus 1filll\n"
    "Copyright @copyright{} COPYRIGHT\n"
    "@end titlepage\n"
    "@headings double\n\n";

  if(fname && *fname)
  {
    FILE *fh= fopen(fname,"r");

    if(fh)
    {
      char *header= (char *)0;
      size_t header_size= 0;

      /* compute the size of the header file */

#ifdef BUGGY_FTELL

      do {

        (void)fgetc(fh);

        if(!feof(fh))
          ++header_size;

      } while(!feof(fh) || ferror(fh))

#else /* ftell() works fine */

      if( fseek(fh,0L,2L) >= 0) /* 2 == OFFSET_END */
        header_size= ftell(fh);

      else
        err= __LINE__;

#endif /* BUGGY_FTELL */

      if(!ferror(fh) && header_size > 0)
      {
        if(fseek(fh,-header_size,1L) < 0) /* 1 == OFFSET_CURRENT */
          err= __LINE__;
      }
      else err= __LINE__;


      /* load the header */

      if(err == 0)
      {
        if( (header= (char *)malloc( (header_size + 1) * sizeof(char) )) )
        {
          fread(header, sizeof(char), header_size, fh);
          header[header_size]= '\0';

          if( ferror(fh) )
          {
            free(header);
            header= (char *)0;
            err= __LINE__;
          }
        }
        else err= __LINE__;
      }

      if(err == 0)
      {
        char *x= strexpand(header, header_macros);

        if(x)
        {
          fputs(x,fp);
          free(x);
        }
        else /* out of memory */
          err= __LINE__;
      }

      fclose(fh);
    }
  }
Exemplo n.º 9
0
/*  error
 *
 *  Outputs an error message (note: msg is passed optionally).
 *  If an error is found, the variable "errflag" is set and subsequent
 *  errors are ignored until lex() finds a semicolumn or a keyword
 *  (lex() resets "errflag" in that case).
 *
 *  Global references: inpfname   (referred to only)
 *                     fline      (referred to only)
 *                     fcurrent   (referred to only)
 *                     errflag    (altered)
 */
int
error(int number, ...)
{
   static int          lastline, lastfile, errorcount;
   char               *msg;
   va_list             argptr;
   char                string[1024];
   int start;

   /* errflag is reset on each semicolon.
    * In a two-pass compiler, an error should not be reported twice. Therefore
    * the error reporting is enabled only in the second pass (and only when
    * actually producing output). Fatal errors may never be ignored.
    */
   if (((errflag) || (sc_status != statWRITE)) &&
       ((number < 100) || (number >= 200)))
     return 0;

   if (number < 100)
     {
	if (number > 74) number = 74;
	msg = errmsg[number - 1];
	errflag = TRUE;	/* set errflag (skip rest of erroneous expression) */
	errnum++;
     }
   else if (number < 200)
     {
	if (number > 107) number = 107;
	msg = fatalmsg[number - 100];
	errnum++; /* a fatal error also counts as an error */
     }
   else
     {
	msg = warnmsg[number - 200];
	warnnum++;
     }

   strexpand(string, (unsigned char *)msg, sizeof string, SCPACK_TABLE);

   va_start(argptr, number);

   start = (errstart == fline) ? -1 : errstart;

   if (sc_error(number, string, inpfname, start, fline, argptr))
   {
      sc_closeasm(outf);
      outf = NULL;
      longjmp(errbuf, 3);
   }

   va_end(argptr);

   if (((number >= 100) && (number < 200)) || (errnum > 250))
     {
	va_start(argptr, number);
	sc_error(0, "\nCompilation aborted.", NULL, 0, 0, argptr);
	va_end(argptr);

	if (outf)
	  {
	     sc_closeasm(outf);
	     outf = NULL;
	  }			/* if */
	longjmp(errbuf, 2);	/* fatal error, quit */
     }				/* if */

   /* check whether we are seeing many errors on the same line */
   if (((errstart < 0) && (lastline != fline)) ||
       (lastline < errstart) || (lastline > fline) || (fcurrent != lastfile))
      errorcount = 0;
   lastline = fline;
   lastfile = fcurrent;
   if (number < 200)
      errorcount++;
   if (errorcount >= 3)
      error(107); /* too many error/warning messages on one line */
   return 0;
}
Exemplo n.º 10
0
/*
 * Parse the configuration file at `path' and execute the `action' call-back
 * functions for any directives defined by the array of config options (first
 * argument).
 *
 * For unknown directives that are encountered, you can optionally pass a
 * call-back function for the third argument to be called for unknowns.
 *
 * Returns zero on success; otherwise returns -1 and errno should be consulted.
*/
int
parse_config(struct fp_config options[], const char *path,
    int (*unknown)(struct fp_config *option, uint32_t line, char *directive,
    char *value), uint16_t processing_options)
{
	uint8_t bequals;
	uint8_t bsemicolon;
	uint8_t case_sensitive;
	uint8_t comment = 0;
	uint8_t end;
	uint8_t found;
	uint8_t have_equals = 0;
	uint8_t quote;
	uint8_t require_equals;
	uint8_t strict_equals;
	char p[2];
	char *directive;
	char *t;
	char *value;
	int error;
	int fd;
	ssize_t r = 1;
	uint32_t dsize;
	uint32_t line = 1;
	uint32_t n;
	uint32_t vsize;
	uint32_t x;
	off_t charpos;
	off_t curpos;
	char rpath[PATH_MAX];

	/* Sanity check: if no options and no unknown function, return */
	if (options == NULL && unknown == NULL)
		return (-1);

	/* Processing options */
	bequals = (processing_options & FP_BREAK_ON_EQUALS) == 0 ? 0 : 1;
	bsemicolon = (processing_options & FP_BREAK_ON_SEMICOLON) == 0 ? 0 : 1;
	case_sensitive = (processing_options & FP_CASE_SENSITIVE) == 0 ? 0 : 1;
	require_equals = (processing_options & FP_REQUIRE_EQUALS) == 0 ? 0 : 1;
	strict_equals = (processing_options & FP_STRICT_EQUALS) == 0 ? 0 : 1;

	/* Initialize strings */
	directive = value = 0;
	vsize = dsize = 0;

	/* Resolve the file path */
	if (realpath(path, rpath) == 0)
		return (-1);

	/* Open the file */
	if ((fd = open(rpath, O_RDONLY)) < 0)
		return (-1);

	/* Read the file until EOF */
	while (r != 0) {
		r = read(fd, p, 1);

		/* skip to the beginning of a directive */
		while (r != 0 && (isspace(*p) || *p == '#' || comment ||
		    (bsemicolon && *p == ';'))) {
			if (*p == '#')
				comment = 1;
			else if (*p == '\n') {
				comment = 0;
				line++;
			}
			r = read(fd, p, 1);
		}
		/* Test for EOF; if EOF then no directive was found */
		if (r == 0) {
			close(fd);
			return (0);
		}

		/* Get the current offset */
		curpos = lseek(fd, 0, SEEK_CUR) - 1;
		if (curpos == -1) {
			close(fd);
			return (-1);
		}

		/* Find the length of the directive */
		for (n = 0; r != 0; n++) {
			if (isspace(*p))
				break;
			if (bequals && *p == '=') {
				have_equals = 1;
				break;
			}
			if (bsemicolon && *p == ';')
				break;
			r = read(fd, p, 1);
		}

		/* Test for EOF, if EOF then no directive was found */
		if (n == 0 && r == 0) {
			close(fd);
			return (0);
		}

		/* Go back to the beginning of the directive */
		error = (int)lseek(fd, curpos, SEEK_SET);
		if (error == (curpos - 1)) {
			close(fd);
			return (-1);
		}

		/* Allocate and read the directive into memory */
		if (n > dsize) {
			if ((directive = realloc(directive, n + 1)) == NULL) {
				close(fd);
				return (-1);
			}
			dsize = n;
		}
		r = read(fd, directive, n);

		/* Advance beyond the equals sign if appropriate/desired */
		if (bequals && *p == '=') {
			if (lseek(fd, 1, SEEK_CUR) != -1)
				r = read(fd, p, 1);
			if (strict_equals && isspace(*p))
				*p = '\n';
		}

		/* Terminate the string */
		directive[n] = '\0';

		/* Convert directive to lower case before comparison */
		if (!case_sensitive)
			strtolower(directive);

		/* Move to what may be the start of the value */
		if (!(bsemicolon && *p == ';') &&
		    !(strict_equals && *p == '=')) {
			while (r != 0 && isspace(*p) && *p != '\n')
				r = read(fd, p, 1);
		}

		/* An equals sign may have stopped us, should we eat it? */
		if (r != 0 && bequals && *p == '=' && !strict_equals) {
			have_equals = 1;
			r = read(fd, p, 1);
			while (r != 0 && isspace(*p) && *p != '\n')
				r = read(fd, p, 1);
		}

		/* If no value, allocate a dummy value and jump to action */
		if (r == 0 || *p == '\n' || *p == '#' ||
		    (bsemicolon && *p == ';')) {
			/* Initialize the value if not already done */
			if (value == NULL && (value = malloc(1)) == NULL) {
				close(fd);
				return (-1);
			}
			value[0] = '\0';
			goto call_function;
		}

		/* Get the current offset */
		curpos = lseek(fd, 0, SEEK_CUR) - 1;
		if (curpos == -1) {
			close(fd);
			return (-1);
		}

		/* Find the end of the value */
		quote = 0;
		end = 0;
		while (r != 0 && end == 0) {
			/* Advance to the next character if we know we can */
			if (*p != '\"' && *p != '#' && *p != '\n' &&
			    (!bsemicolon || *p != ';')) {
				r = read(fd, p, 1);
				continue;
			}

			/*
			 * If we get this far, we've hit an end-key
			 */

			/* Get the current offset */
			charpos = lseek(fd, 0, SEEK_CUR) - 1;
			if (charpos == -1) {
				close(fd);
				return (-1);
			}

			/*
			 * Go back so we can read the character before the key
			 * to check if the character is escaped (which means we
			 * should continue).
			 */
			error = (int)lseek(fd, -2, SEEK_CUR);
			if (error == -3) {
				close(fd);
				return (-1);
			}
			r = read(fd, p, 1);

			/*
			 * Count how many backslashes there are (an odd number
			 * means the key is escaped, even means otherwise).
			 */
			for (n = 1; *p == '\\'; n++) {
				/* Move back another offset to read */
				error = (int)lseek(fd, -2, SEEK_CUR);
				if (error == -3) {
					close(fd);
					return (-1);
				}
				r = read(fd, p, 1);
			}

			/* Move offset back to the key and read it */
			error = (int)lseek(fd, charpos, SEEK_SET);
			if (error == (charpos - 1)) {
				close(fd);
				return (-1);
			}
			r = read(fd, p, 1);

			/*
			 * If an even number of backslashes was counted meaning
			 * key is not escaped, we should evaluate what to do.
			 */
			if ((n & 1) == 1) {
				switch (*p) {
				case '\"':
					/*
				 	 * Flag current sequence of characters
					 * to follow as being quoted (hashes
					 * are not considered comments).
					 */
					quote = !quote;
					break;
				case '#':
					/*
					 * If we aren't in a quoted series, we
					 * just hit an inline comment and have
					 * found the end of the value.
					 */
					if (!quote)
						end = 1;
					break;
				case '\n':
					/*
					 * Newline characters must always be
					 * escaped, whether inside a quoted
					 * series or not, otherwise they
					 * terminate the value.
					 */
					end = 1;
				case ';':
					if (!quote && bsemicolon)
						end = 1;
					break;
				}
			} else if (*p == '\n')
				/* Escaped newline character. increment */
				line++;

			/* Advance to the next character */
			r = read(fd, p, 1);
		}

		/* Get the current offset */
		charpos = lseek(fd, 0, SEEK_CUR) - 1;
		if (charpos == -1) {
			close(fd);
			return (-1);
		}

		/* Get the length of the value */
		n = (uint32_t)(charpos - curpos);
		if (r != 0) /* more to read, but don't read ending key */
			n--;

		/* Move offset back to the beginning of the value */
		error = (int)lseek(fd, curpos, SEEK_SET);
		if (error == (curpos - 1)) {
			close(fd);
			return (-1);
		}

		/* Allocate and read the value into memory */
		if (n > vsize) {
			if ((value = realloc(value, n + 1)) == NULL) {
				close(fd);
				return (-1);
			}
			vsize = n;
		}
		r = read(fd, value, n);

		/* Terminate the string */
		value[n] = '\0';

		/* Cut trailing whitespace off by termination */
		t = value + n;
		while (isspace(*--t))
			*t = '\0';

		/* Escape the escaped quotes (replaceall is in string_m.c) */
		x = strcount(value, "\\\""); /* in string_m.c */
		if (x != 0 && (n + x) > vsize) {
			if ((value = realloc(value, n + x + 1)) == NULL) {
				close(fd);
				return (-1);
			}
			vsize = n + x;
		}
		if (replaceall(value, "\\\"", "\\\\\"") < 0) {
			/* Replace operation failed for some unknown reason */
			close(fd);
			return (-1);
		}

		/* Remove all new line characters */
		if (replaceall(value, "\\\n", "") < 0) {
			/* Replace operation failed for some unknown reason */
			close(fd);
			return (-1);
		}

		/* Resolve escape sequences */
		strexpand(value); /* in string_m.c */

call_function:
		/* Abort if we're seeking only assignments */
		if (require_equals && !have_equals)
			return (-1);

		found = have_equals = 0; /* reset */

		/* If there are no options defined, call unknown and loop */
		if (options == NULL && unknown != NULL) {
			error = unknown(NULL, line, directive, value);
			if (error != 0) {
				close(fd);
				return (error);
			}
			continue;
		}

		/* Loop through the array looking for a match for the value */
		for (n = 0; options[n].directive != NULL; n++) {
			error = fnmatch(options[n].directive, directive,
			    FNM_NOESCAPE);
			if (error == 0) {
				found = 1;
				/* Call function for array index item */
				if (options[n].action != NULL) {
					error = options[n].action(
					    &options[n],
					    line, directive, value);
					if (error != 0) {
						close(fd);
						return (error);
					}
				}
			} else if (error != FNM_NOMATCH) {
				/* An error has occurred */
				close(fd);
				return (-1);
			}
		}
		if (!found && unknown != NULL) {
			/*
			 * No match was found for the value we read from the
			 * file; call function designated for unknown values.
			 */
			error = unknown(NULL, line, directive, value);
			if (error != 0) {
				close(fd);
				return (error);
			}
		}
	}

	close(fd);
	return (0);
}