Пример #1
0
Файл: cpp4.c Проект: Akaito/bgfx
INLINE FILE_LOCAL
ReturnCode stparmscan(struct Global *global, int delim)
{
  /*
   * Normal string parameter scan.
   */
  
  unsigned char	*wp;
  int i;
  ReturnCode ret;
      
  wp = (unsigned char *)global->workp;	/* Here's where it starts       */
  ret=scanstring(global, delim, save);
  if(ret)
    return(ret);		/* Exit on scanstring error	*/
  global->workp[-1] = EOS;		/* Erase trailing quote 	*/
  wp++;				/* -> first string content byte */
  for (i = 0; i < global->nargs; i++) {
    if (streq(global->parlist[i], (char *)wp)) {
      *wp++ = MAC_PARM + PAR_MAC;	/* Stuff a magic marker */
      *wp++ = (i + MAC_PARM);         /* Make a formal marker */
      *wp = wp[-3];			/* Add on closing quote */
      global->workp = (char *)wp + 1; 	/* Reset string end	*/
      return(FPP_OK);
    }
  }
  global->workp[-1] = wp[-1];	/* Nope, reset end quote.	*/
  return(FPP_OK);
}
Пример #2
0
/*
 * Normal string parameter scan.
 */
void stparmscan(int delim)
{
    char* wp;
    int i;

    wp = workp;                     /* Here's where it starts       */
    if (!scanstring(delim, save))
        return;                     /* Exit on scanstring error     */
    workp[-1] = EOS;                /* Erase trailing quote         */
    wp++;                           /* -> first string content byte */
    for (i = 0; i < nargs; i++)
    {
        if (streq(parlist[i], wp))
        {
#ifdef SOLAR
            *wp++ = DEL;
            *wp++ = MAC_PARM + PAR_MAC;     /* Stuff a magic marker */
            *wp++ = (char)(i + MAC_PARM);   /* Make a formal marker */
            *wp = wp[-4];                   /* Add on closing quote */
            workp = wp + 1;                 /* Reset string end     */
#else
            *wp++ = MAC_PARM + PAR_MAC;     /* Stuff a magic marker */
            *wp++ = (i + MAC_PARM);         /* Make a formal marker */
            *wp = wp[-3];                   /* Add on closing quote */
            workp = wp + 1;                 /* Reset string end     */
#endif
            return;
        }
    }
    workp[-1] = wp[-1];             /* Nope, reset end quote.       */
}
Пример #3
0
void lunascan::next()
   {
   if (CODESTACKSIZE<1) ERRORMSG();

   clear();

   scanspace();

   if (CH!='\0')
      if (CH>='0' && CH<='9') scanvalue();
      else if (CH=='-') scanminus();
      else if (CH=='\'') scanchar();
      else if (CH=='"') scanstring();
      else if ((CH>='a' && CH<='z') || (CH>='A' && CH<='Z') || CH=='_') scanidentifier();
      else scanspecial();
   }
Пример #4
0
char *read_string(char *prompt, char *def) {

  short esito;
  static char stringa[EASYIO_MAX_STR_LEN];

  for (int timeout = 0; timeout <= 5; timeout++) {
    fprintf(FPTR, "%s [%s] > ", prompt, def);
    esito = scanstring(stringa);
    switch (esito) {
      case EASYIO_DEFAULT:
        return (def);
      case EASYIO_OKAY:
        return (stringa);
      case EASYIO_ERROR:
        beep();
        break;
    }
  }
  fprintf(FPTR, "\n FATAL ERROR: too many wrong attempts ");
  fprintf(FPTR, "in read_string() \n");
  exit(-1);
  return (false);        // not used: just to be nice with the compiler
}
Пример #5
0
/*
 * Collect the actual parameters for this macro.  TRUE if ok.
 */
FILE_LOCAL int expcollect()
{
    int c;
    int paren;                  /* For embedded ()'s    */
    for (;;)
    {
        paren = 0;                          /* Collect next arg.    */
        while ((c = skipws()) == '\n')      /* Skip over whitespace */
            wrongline = TRUE;               /* and newlines.        */
        if (c == ')')                       /* At end of all args?  */
        {
            /*
             * Note that there is a guard byte in parm[]
             * so we don't have to check for overflow here.
             */
            *parmp = EOS;                   /* Make sure terminated */
            break;                          /* Exit collection loop */
        }
        else if (nargs >= LASTPARM)
            cfatal("Too many arguments in macro expansion", NULLST);
        parlist[nargs++] = parmp;           /* At start of new arg  */
        for (;; c = cget())                 /* Collect arg's bytes  */
        {
            if (c == EOF_CHAR)
            {
                cerror("end of file within macro argument", NULLST);
                return FALSE;             /* Sorry.               */
            }
            else if (c == '\\')             /* Quote next character */
            {
                charput(c);                 /* Save the \ for later */
                charput(cget());            /* Save the next char.  */
                continue;                   /* And go get another   */
            }
            else if (type[c] == QUO)        /* Start of string?     */
            {
                scanstring(c, charput);     /* Scan it off          */
                continue;                   /* Go get next char     */
            }
            else if (c == '(')              /* Worry about balance  */
                paren++;                    /* To know about commas */
            else if (c == ')')              /* Other side too       */
            {
                if (paren == 0)             /* At the end?          */
                {
                    unget();                /* Look at it later     */
                    break;                  /* Exit arg getter.     */
                }
                paren--;                    /* More to come.        */
            }
            else if (c == ',' && paren == 0) /* Comma delimits args */
                break;
            else if (c == '\n')             /* Newline inside arg?  */
                wrongline = TRUE;           /* We'll need a #line   */
            charput(c);                     /* Store this one       */
        }                                   /* Collect an argument  */
        charput(EOS);                       /* Terminate argument   */
#if OSL_DEBUG_LEVEL > 1
        if (debug)
            fprintf( pCppOut, "parm[%d] = \"%s\"\n", nargs, parlist[nargs - 1]);
#endif
    }                                       /* Collect all args.    */
    return TRUE;                            /* Normal return        */
}
Пример #6
0
/*
 * Main process for cpp -- copies tokens from the current input
 * stream (main file, include file, or a macro) to the output
 * file.
 */
void cppmain()
{
    int c;              /* Current character    */
    int counter;        /* newlines and spaces  */

    /*
     * Explicitly output a #line at the start of cpp output so
     * that lint (etc.) knows the name of the original source
     * file.  If we don't do this explicitly, we may get
     * the name of the first #include file instead.
     * We also seem to need a blank line following that first #line.
     */
#ifdef EVALDEFS
    if ( !bIsInEval )
#endif
    {
        sharp();
        PUTCHAR('\n');
    }
    /*
     * This loop is started "from the top" at the beginning of each line
     * wrongline is set TRUE in many places if it is necessary to write
     * a #line record.  (But we don't write them when expanding macros.)
     *
     * The counter variable has two different uses:  at
     * the start of a line, it counts the number of blank lines that
     * have been skipped over.  These are then either output via
     * #line records or by outputting explicit blank lines.
     * When expanding tokens within a line, the counter remembers
     * whether a blank/tab has been output.  These are dropped
     * at the end of the line, and replaced by a single blank
     * within lines.
     */
    for (;;)
    {
        counter = 0;                        /* Count empty lines    */
        for (;;)
        {                                   /* For each line, ...   */
            while (type[(c = get())] == SPA) /* Skip leading blanks */
                ;                           /* in this line.        */
            if (c == '\n')                  /* If line's all blank, */
                ++counter;                  /* Do nothing now       */
            else if (c == '#')
            {            /* Is 1st non-space '#' */
                keepcomments = FALSE;       /* Don't pass comments  */
                counter = control(counter); /* Yes, do a #command   */
                keepcomments = (cflag && compiling);
            }
            else if (c == EOF_CHAR)         /* At end of file?      */
            {
                break;
            }
            else if (!compiling)
            {                               /* #ifdef false?        */
                skipnl();                   /* Skip to newline      */
                counter++;                  /* Count it, too.       */
            }
            else
            {
                break;                      /* Actual token         */
            }
        }
        if (c == EOF_CHAR)                  /* Exit process at      */
            break;                          /* End of file          */
        /*
         * If the loop didn't terminate because of end of file, we
         * know there is a token to compile.  First, clean up after
         * absorbing newlines.  counter has the number we skipped.
         */
        if ((wrongline && infile->fp != NULL) || counter > 4)
            sharp();                        /* Output # line number */
        else
        {                                   /* If just a few, stuff */
            while (--counter >= 0)          /* them out ourselves   */
                PUTCHAR('\n');
        }
        /*
         * Process each token on this line.
         */
        unget();                            /* Reread the char.     */
        for (;;)
        {                                   /* For the whole line,  */
            do
            {                            /* Token concat. loop   */
                for (counter = 0; type[(c = get())] == SPA;)
                {
#if COMMENT_INVISIBLE
                    if (c != COM_SEP)
#endif
                    counter++;              /* Skip over blanks     */

                }
                if (c == EOF_CHAR || c == '\n')
                    goto end_line;          /* Exit line loop       */
                else if (counter > 0)       /* If we got any spaces */
                    PUTCHAR(' ');           /* Output one space     */
                c = macroid(c);             /* Grab the token       */
            }
            while (type[c] == LET && catenate());

            if (c == EOF_CHAR || c == '\n') /* From macro exp error */
                goto end_line;              /* Exit line loop       */

            switch (type[c])
            {
            case LET:
                fputs(token, pCppOut);       /* Quite ordinary token */
#ifdef EVALDEFS
                {
                    int len;
                    if ( bIsInEval
                         && nEvalOff + (len=strlen(token)) < NEVALBUF )
                    {
                        strcpy( &EvalBuf[nEvalOff], token );
                        nEvalOff += len;
                    }
                }
#endif
                break;


            case DIG:                       /* Output a number      */
            case DOT:                       /* Dot may begin floats */
#ifdef EVALDEFS
                if ( bIsInEval )
                    scannumber(c, outputEval);
                else
                    scannumber(c, output);
#else
                scannumber(c, output);
#endif
                break;

            case QUO:                       /* char or string const */
                scanstring(c, output);      /* Copy it to output    */
                break;

            default:                        /* Some other character */
                cput(c);                    /* Just output it       */
#ifdef EVALDEFS
                if ( bIsInEval && nEvalOff < NEVALBUF )
                    EvalBuf[nEvalOff++] = c;
#endif
                break;
            }                               /* Switch ends          */
        }                                   /* Line for loop        */
      end_line:
        if (c == '\n')
        {                                   /* Compiling at EOL?    */
            PUTCHAR('\n');                  /* Output newline, if   */
            if (infile->fp == NULL)         /* Expanding a macro,   */
                wrongline = TRUE;           /* Output # line later  */
        }
    }                                       /* Continue until EOF   */
#ifdef EVALDEFS
    if ( bIsInEval )
        EvalBuf[nEvalOff++] = '\0';
#endif
}
Пример #7
0
Файл: cpp4.c Проект: Akaito/bgfx
INLINE FILE_LOCAL
ReturnCode expcollect(struct Global *global)
{
  /*
   * Collect the actual parameters for this macro.
   */

  int c;
  int paren;		    /* For embedded ()'s    */
  ReturnCode ret;
      
  for (;;) {
    paren = 0;			    /* Collect next arg.    */
    while ((c = skipws(global)) == '\n')/* Skip over whitespace */
      global->wrongline = TRUE;		/* and newlines.	*/
    if (c == ')') {                     /* At end of all args?  */
      /*
       * Note that there is a guard byte in parm[]
       * so we don't have to check for overflow here.
       */
      *global->parmp = EOS;	    /* Make sure terminated */
      break;			    /* Exit collection loop */
    }
    else if (global->nargs >= LASTPARM) {
      cfatal(global, FATAL_TOO_MANY_ARGUMENTS_EXPANSION);
      return(FPP_TOO_MANY_ARGUMENTS);
    }
    global->parlist[global->nargs++] = global->parmp; /* At start of new arg */
    for (;; c = cget(global)) {               /* Collect arg's bytes  */
      if (c == EOF_CHAR) {
	cerror(global, ERROR_EOF_IN_ARGUMENT);
	return(FPP_EOF_IN_MACRO); /* Sorry.               */
      }
      else if (c == '\\') {             /* Quote next character */
	charput(global, c);             /* Save the \ for later */
	charput(global, cget(global));  /* Save the next char.  */
	continue;			/* And go get another   */
      }
      else if (type[c] == QUO) {        /* Start of string?     */
	ret=scanstring(global, c, (ReturnCode (*)(struct Global *, int))charput); /* Scan it off    */
	if(ret)
	  return(ret);
	continue;			    /* Go get next char     */
      }
      else if (c == '(')                /* Worry about balance  */
	paren++;			/* To know about commas */
      else if (c == ')') {              /* Other side too       */
	if (paren == 0) {               /* At the end?          */
	  unget(global);                /* Look at it later     */
	  break;			/* Exit arg getter.     */
	}
	paren--;			/* More to come.        */
      }
      else if (c == ',' && paren == 0)  /* Comma delimits args  */
	break;
      else if (c == '\n')               /* Newline inside arg?  */
	global->wrongline = TRUE;	/* We'll need a #line   */
      charput(global, c);               /* Store this one       */
    }				        /* Collect an argument  */
    charput(global, EOS);               /* Terminate argument   */
  }				        /* Collect all args.    */
  return(FPP_OK);                       /* Normal return        */
}
Пример #8
0
Файл: cpp1.c Проект: kwertz/fcpp
INLINE FILE_LOCAL
ReturnCode cppmain(struct Global *global)
{
  /*
   * Main process for cpp -- copies tokens from the current input
   * stream (main file, include file, or a macro) to the output
   * file.
   */

  int c;        /* Current character    */
  int counter;  /* newlines and spaces  */
  ReturnCode ret; /* return code variable type */

  long bracelevel = 0;
  long parenlevel = 0;
  long bracketlevel = 0;
  int fake = 0;

#define MAX_FUNC_LENGTH 50

  char tempfunc[MAX_FUNC_LENGTH + 1];
  char tempfunc2[MAX_FUNC_LENGTH + 1];
  char define = 0; /* probability of a function define phase in the program */
  char prev = 0; /* previous type */
  char go = 0;
  char include = 0;
  char initfunc = 0;

  /* Initialize for reading tokens */
  global->tokenbsize = 50;
  global->tokenbuf = malloc(global->tokenbsize + 1);
  if(!global->tokenbuf)
    return(FPP_OUT_OF_MEMORY);

  global->functionname = malloc(global->tokenbsize + 1);
  if(!global->functionname)
    return(FPP_OUT_OF_MEMORY);
  global->functionname[0] = '\0';

  if(global->showspace) {
    global->spacebuf = (char *)malloc(MAX_SPACE_SIZE);
    if(!global->spacebuf)
      return(FPP_OUT_OF_MEMORY);
  }

  if(global->showversion)
      Error(global, VERSION_TEXT);

  /*
   * Explicitly output a #line at the start of cpp output so
   * that lint (etc.) knows the name of the original source
   * file.  If we don't do this explicitly, we may get
   * the name of the first #include file instead.
   */
  if(global->linelines) /* if #line lines are wanted! */
    sharp(global);
  /*
   * This loop is started "from the top" at the beginning of each line
   * wrongline is set TRUE in many places if it is necessary to write
   * a #line record.  (But we don't write them when expanding macros.)
   *
   * The counter variable has two different uses:  at
   * the start of a line, it counts the number of blank lines that
   * have been skipped over. These are then either output via
   * #line records or by outputting explicit blank lines.
   * When expanding tokens within a line, the counter remembers
   * whether a blank/tab has been output.  These are dropped
   * at the end of the line, and replaced by a single blank
   * within lines.
   */

  include = global->included;

  while(include--) {
    openinclude(global, global->include[include], TRUE);
  }
  
  for (;;) {
    counter = 0;                        /* Count empty lines    */
    for (;;) {                          /* For each line, ...   */
      global->comment = FALSE;          /* No comment yet!      */
      global->chpos = 0;                /* Count whitespaces    */
      while (type[(c = get(global))] == SPA)  /* Skip leading blanks */
	if(global->showspace) {
	  if(global->chpos<MAX_SPACE_SIZE-1)
	    /* we still have buffer to store this! */
	    global->spacebuf[global->chpos++]=(char)c;
	}
      if (c == '\n') {                  /* If line's all blank, */
	if(global->comment) {
	  /* A comment was output! */
	  Putchar(global, '\n');
	}
	else
	  ++counter;                    /* Do nothing now       */
      }
      else if (c == '#') {              /* Is 1st non-space '#' */
	global->keepcomments = FALSE;   /* Don't pass comments  */
	ret = control(global, &counter); /* Yes, do a #command   */
	if(ret)
	  return(ret);
	global->keepcomments = (global->cflag && compiling);
      }
      else if (c == EOF_CHAR)           /* At end of file?      */
	break;
      else if (!compiling) {            /* #ifdef false?        */
	skipnl(global);                 /* Skip to newline      */
	counter++;                      /* Count it, too.       */
      } else {
	break;                          /* Actual token         */
      }
    }
    if (c == EOF_CHAR)                  /* Exit process at      */
      break;                            /* End of file          */
    /*
     * If the loop didn't terminate because of end of file, we
     * know there is a token to compile.  First, clean up after
     * absorbing newlines.  counter has the number we skipped.
     */
    if(global->linelines) { /* if #line lines are wanted! */
      if ((global->wrongline && global->infile->fp != NULL) || counter > 4)
        sharp(global);                    /* Output # line number */
      else {                              /* If just a few, stuff */
        while (--counter >= 0)            /* them out ourselves   */
	  Putchar(global, (int)'\n');
      }
    }
    if(global->showspace) {
      /* Show all whitespaces! */
      global->spacebuf[global->chpos] = '\0';
      Putstring(global, global->spacebuf);
    }
    
    /*
     * Process each token on this line.
     */
    unget(global);                      /* Reread the char.     */
    for (;;) {                          /* For the whole line,  */
      do {                              /* Token concat. loop   */
	for (global->chpos = counter = 0; (type[(c = get(global))] == SPA);) {
#if COMMENT_INVISIBLE
	  if (c != COM_SEP)
	    counter++;
#else
	  if(global->showspace && global->chpos < MAX_SPACE_SIZE-1) {
	    global->spacebuf[global->chpos++]=(char)c;
	  }
	  counter++;            /* Skip over blanks     */
#endif
	}
	if (c == EOF_CHAR || c == '\n')
	  break;                      /* Exit line loop       */
	else if (counter > 0) {       /* If we got any spaces */
	  if(!global->showspace)      /* We don't output all spaces */
	    Putchar(global, (int)' ');/* Output one space     */
	  else {
	    global->spacebuf[global->chpos] = '\0';
	    Putstring(global, global->spacebuf); /* Output all whitespaces */
	  }
	}
	if(ret=macroid(global, &c))   /* Grab the token       */
	  return(ret);
      } while (type[c] == LET && catenate(global, &ret) && !ret);
      if(ret)
	/* If the loop was broken because of a fatal error! */
	return(ret);
      if (c == EOF_CHAR || c == '\n') /* From macro exp error */
	break;                        /* Exit line loop       */
      go++;
      switch (type[c]) {
      case LET:
	go =0;
	/* Quite ordinary token */
	Putstring(global, global->tokenbuf);
	
	if(!define) {
	  /* Copy the name */
	  strncpy(tempfunc, global->tokenbuf, MAX_FUNC_LENGTH);
          tempfunc[MAX_FUNC_LENGTH]=0;
	}
	/* fputs(global->tokenbuf, stdout); */
	break;
      case DIG:                 /* Output a number      */
      case DOT:                 /* Dot may begin floats */
	go = 0;
	ret=scannumber(global, c, (ReturnCode(*)(struct Global *, int))output);
	if(ret)
	  return(ret);
	break;
      case QUO:                 /* char or string const */
	go = 0;
	/* Copy it to output */
        if(!global->webmode) {
          ret=scanstring(global, c,
                         (ReturnCode(*)(struct Global *, int))output);
          if(ret)
            return(ret);
          break;
        }
        /* FALLTHROUGH */
      default:                  /* Some other character */
	
	define++;
	switch(c) {
	case '{':
	  if(! bracelevel++ && define > 2) {
	    /*
	     * This is a starting brace. If there is a probability of a
	     * function defining, we copy the `tempfunc' function name to
	     * `global->functionname'.
	     */
	    strcpy(global->functionname, tempfunc2);
	    global->funcline = global->line;

		if(global->outputfunctions) {
			/*
			 * Output the discovered function name to stderr!
			 */
			Error(global, "#> Function defined at line %d: %s <#\n",
				  global->line,
				  global->functionname);
		}

	    if(global->initialfunc) {
		int a;
		for(a=0; a<global->excluded; a++) {
		    /* check for excluded functions */
		    if(!strcmp(global->functionname,
			       global->excludedinit[a]))
			break;
		}
		if(a==global->excluded) {
		    expstuff(global, "__brace__", "{");
		    expstuff(global, "__init_func__", global->initialfunc);
		    initfunc = TRUE;
		}
	    }

	  }
	  break;
	case '}':
	  go = 0;
	  if( (--bracelevel == initfunc) &&
	     strcmp(global->infile->filename, "__init_func__") ) {
	    /* we just stepped out of the function! */
	    global->functionname[0] = '\0';
	    global->funcline = 0;
	    define = 1;

	    if(initfunc) {
	      Putchar(global, '}');
	      bracelevel--;
	      initfunc=0;
	    }
	  }
	  fake = 0;
	  break;
	  
	case ';':
	case ',':
	  if(go == 2) {
	    define = 1;
	    fake = 0;
	    go--;
	    break;
	  }
	  break;
	case '(':
	  if(! parenlevel++ && !bracelevel) {
	    if(go == 2) {
	      /* foobar(text) -> "(" is found. This can't be a
		 function */
	      go--;
	      define = 1;
	      break;
	    }
	    if( define < 2 && prev == LET) {
	      /* This is the first parenthesis on the ground brace
		 level, and we did previously not have a probable
		 function name */
	      strncpy(tempfunc2, global->tokenbuf, MAX_FUNC_LENGTH);
              tempfunc2[MAX_FUNC_LENGTH]=0;
	      define++;
	    }
	    else {
	      /* we have a fake start */
	      fake++;
	    }
	  }
	  break;
	case ')':
	  if(! --parenlevel && !bracelevel && define>1 && !fake) {
	    /*
	     * The starting parentheses level and
	     * the starting brace level.
	     * This might be the start of a function defining coming
	     * up!
	     */
	    define++; /* increase probability */
	    fake = 0;
	    go = 1;
	  }
	  break;
	case '[':
	  bracketlevel++;
	  break;
	case ']':
	  bracketlevel--;
	  break;
	}
	define--; /* decrease function probability */
	
	Putchar(global, c);     /* Just output it       */
	break;
      }                         /* Switch ends          */
      prev = type[c];
    }                           /* Line for loop        */
    
    if (c == '\n') {  /* Compiling at EOL?    */
      Putchar(global, '\n');              /* Output newline, if   */
      if (global->infile->fp == NULL)     /* Expanding a macro,   */
	global->wrongline = TRUE; /* Output # line later        */
    }
  }                             /* Continue until EOF   */

  if(global->showbalance) {
    if(bracketlevel) {
      cwarn(global, WARN_BRACKET_DEPTH, bracketlevel);
    }
    if(parenlevel) {
      cwarn(global, WARN_PAREN_DEPTH, parenlevel);
    }
    if(bracelevel) {
      cwarn(global, WARN_BRACE_DEPTH, bracelevel);
    }
  }
  if (global->wflag) {
    global->out = TRUE;         /* enable output */
    outdefines(global);         /* Write out #defines   */
  }
  return(FPP_OK);
}
Пример #9
0
static int
field_encode_address(const char *name, char **value, int encoding,
		     const char *charset)
{
    int prefixlen = strlen(name) + 2, column = prefixlen, groupflag;
    int asciichars, specialchars, eightbitchars, reformat = 0, errflag = 0;
    size_t len;
    char *mp, *cp = NULL, *output = NULL;
    char *tmpbuf = NULL;
    size_t tmpbufsize = 0;
    struct mailname *mn;
    char errbuf[BUFSIZ];

    /*
     * Because these are addresses, we need to handle them individually.
     *
     * Break them down and process them one by one.  This means we have to
     * rewrite the whole header, but that's unavoidable.
     */

    /*
     * The output headers always have to start with a space first; this
     * is just the way the API works right now.
     */

    output = add(" ", output);

    for (groupflag = 0; (mp = getname(*value)); ) {
    	if ((mn = getm(mp, NULL, 0, errbuf, sizeof(errbuf))) == NULL) {
	    advise(NULL, "%s: %s", errbuf, mp);
	    errflag++;
	    continue;
	}

	reformat = 0;

	/*
	 * We only care if the phrase (m_pers) or any trailing comment
	 * (m_note) have 8-bit characters.  If doing q-p, we also need
	 * to encode anything marked as qspecial().  Unquote it first
	 * so the specialchars count is right.
	 */

	if (! mn->m_pers)
	    goto check_note;

	if ((len = strlen(mn->m_pers)) + 1 > tmpbufsize) {
	    tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = len + 1);
	}

	unquote_string(mn->m_pers, tmpbuf);

	if (scanstring(tmpbuf, &asciichars, &eightbitchars,
		       &specialchars)) {
	    /*
	     * If we have 8-bit characters, encode it.
	     */

	    if (encoding == CE_UNKNOWN)
	    	encoding = pref_encoding(asciichars, specialchars,
					 eightbitchars);

	    /*
	     * This is okay, because the output of unquote_string will be either
	     * equal or shorter than the original.
	     */

	    strcpy(mn->m_pers, tmpbuf);

	    switch (encoding) {

	    case CE_BASE64:
	    	if (field_encode_base64(NULL, &mn->m_pers, charset)) {
		    errflag++;
		    goto out;
		}
		break;

	    case CE_QUOTED:
	    	if (field_encode_quoted(NULL, &mn->m_pers, charset, asciichars,
					eightbitchars + specialchars, 1)) {
		    errflag++;
		    goto out;
		}
		break;

	    default:
		advise(NULL, "Internal error: unknown RFC-2047 encoding type");
		errflag++;
		goto out;
	    }

	    reformat++;
	}

	check_note:

	/*
	 * The "note" field is generally a comment at the end of the address,
	 * at least as how it's implemented here.  Notes are always surrounded
	 * by parenthesis (since they're comments).  Strip them out and
	 * then put them back when we format the final field, but they do
	 * not get encoded.
	 */

	if (! mn->m_note)
	    goto do_reformat;

	if ((len = strlen(mn->m_note)) + 1 > tmpbufsize) {
	    tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = len + 1);
	}

	if (mn->m_note[0] != '(' || mn->m_note[len - 1] != ')') {
	    advise(NULL, "Internal error: Invalid note field \"%s\"",
	    	   mn->m_note);
	    errflag++;
	    goto out;
	}

	strncpy(tmpbuf, mn->m_note + 1, len - 1);
	tmpbuf[len - 2] = '\0';

	if (scanstring(tmpbuf, &asciichars, &eightbitchars,
		       &specialchars)) {
	    /*
	     * If we have 8-bit characters, encode it.
	     */

	    if (encoding == CE_UNKNOWN)
	    	encoding = pref_encoding(asciichars, specialchars,
					 eightbitchars);

	    switch (encoding) {

	    case CE_BASE64:
	    	if (field_encode_base64(NULL, &tmpbuf, charset)) {
		    errflag++;
		    goto out;
		}
		break;

	    case CE_QUOTED:
	    	if (field_encode_quoted(NULL, &tmpbuf, charset, asciichars,
					eightbitchars + specialchars, 1)) {
		    errflag++;
		    goto out;
		}
		break;

	    default:
		advise(NULL, "Internal error: unknown RFC-2047 encoding type");
		errflag++;
		goto out;
	    }

	    reformat++;

	    /*
	     * Make sure the size of tmpbuf is correct (it always gets
	     * reallocated in the above functions).
	     */

	    tmpbufsize = strlen(tmpbuf) + 1;

	    /*
	     * Put the note field back surrounded by parenthesis.
	     */

	    mn->m_note = mh_xrealloc(mn->m_note, tmpbufsize + 2);

	    snprintf(mn->m_note, tmpbufsize + 2, "(%s)", tmpbuf);
	}

do_reformat:

	/*
	 * So, some explanation is in order.
	 *
	 * We know we need to rewrite at least one address in the header,
	 * otherwise we wouldn't be here.  If we had to reformat this
	 * particular address, then run it through adrformat().  Otherwise
	 * we can use m_text directly.
	 */

	/*
	 * If we were in a group but are no longer, make sure we add a
	 * semicolon (which needs to be FIRST, as it needs to be at the end
	 * of the last address).
	 */

	if (groupflag && ! mn->m_ingrp) {
	    output = add(";", output);
	    column += 1;
	}

	groupflag = mn->m_ingrp;

	if (mn->m_gname) {
	    cp = add(mn->m_gname, NULL);
	}

	if (reformat) {
	    cp = add(adrformat(mn), cp);
	} else {
	    cp = add(mn->m_text, cp);
	}

	len = strlen(cp);

	/*
	 * If we're not at the beginning of the line, add a command and
	 * either a space or a newline.
	 */

	if (column != prefixlen) {
	    if (len + column + 2 > OUTPUTLINELEN) {

	    	if ((size_t) (prefixlen + 3) < tmpbufsize)
		    tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = prefixlen + 3);

		snprintf(tmpbuf, tmpbufsize, ",\n%*s", column = prefixlen, "");
		output = add(tmpbuf, output);
	    } else {
	    	output = add(", ", output);
		column += 2;
	    }
	}

	/*
	 * Finally add the address
	 */

	output = add(cp, output);
	column += len;
	free(cp);
	cp = NULL;
    }

    /*
     * Just in case we're at the end of a list
     */

    if (groupflag) {
	output = add(";", output);
    }

    output = add("\n", output);

    free(*value);
    *value = output;
    output = NULL;

out:

    if (tmpbuf)
    	free(tmpbuf);
    if (output)
    	free(output);

    return errflag > 0;
}
Пример #10
0
boolean pathtofilespec ( bigstring bspath, ptrfilespec fs ) {

    //
    // 2010-01-24 creedon: fix for relative paths not working on mac,
    //                     bsfullpath was ending up with :: in it as well as
    //                     the full path to the application, see initfsdefault
    //                     function
    //
	// 2009-08-30 aradke: refactored mac version to make it easier to understand.
	//			fixed bug where a bspath containing a non-existing volume name was accepted as valid,
	//			e.g. filespec("foobar:"), thus deviating from previous behaviour.
	//
	// 2006-10-16 creedon: for Mac, FSRef-ized
	//
	// 5.0d8 dmb: clear fs first thing
	//
	// 2.1b2 dmb: use new fsdefault for building filespec. note that if bspath
    //            isn't a partial path, the vref and dirid will be ignored.
	//
	// 2.1b2 dmb: added special case for empty string.  also, added drive
    //            number interpretation here.
	//
	// 1993-06-11 dmb: if FSMakeFSSpec returns fnfErr, the spec is cool (but
    //                 file doesn't exist)
	//
	// 1991-012-17 dmb: dont append path to default directory if it's a full
    //                  path
	//
	// 1991-07-05 dmb: use FSMakeFSSpec if it's available.  since it only
    //                 returns noErr if the file exists, and we want to handle
	//                 non-existant files, we don't give up right away.
	//
	
	#ifdef MACVERSION
		FSRef fsr;
		bigstring bspathtmp, bsfullpath, bsfile, bsfolder;
		short ix = 1;
		boolean flvolume = false;
	#endif

	#ifdef WIN95VERSION
		bigstring bsfolder;
	#endif

	clearbytes ( fs, sizeof ( *fs ) );

	if ( isemptystring ( bspath ) )
		return ( true );
		
	#ifdef MACVERSION

		// create cleaned-up full path representation of our input suitable for pathtosref
	
		copystring ( bspath, bspathtmp );

		cleanendoffilename ( bspathtmp );
		
		if ( scanstring ( ':', bspath, &ix ) && ( ix > 1 ) ) {
		
			// contains a colon but doesn't start with one, so it must be a full path
			
			if ( ix == stringlength ( bspath ) )	// the colon we found is the last char, so bspath is a volume name
				flvolume = true;
                
			copystring ( bspathtmp, bsfullpath );
			}
            
		else {
		
			// it's a partial path, prefix with default directory (see initfsdefault)
		
			if ( ! filespectopath ( &fsdefault, bsfullpath ) )	// get path of default directory
				return ( false );
                
           // delete first path separator if partial path begins with one because bsfullpath always ends with one
           
			if ( bspathtmp [ 1 ] == chpathseparator )
				deletefirstchar ( bspathtmp );
                
			pushstring ( bspathtmp, bsfullpath );	// append partial path
			}
            
		// now see if the full path resolves 
			
		if ( pathtofsref ( bsfullpath, &fsr ) == noErr ) {

			return ( macmakefilespec ( &fsr, fs ) == noErr );
			}
			
		// full path did not resolve but we actually only require the parent folder to exist
		
		if ( ! flvolume ) {		// volumes don't have a parent folder
		
			filefrompath ( bsfullpath, bsfile );
			
			folderfrompath ( bsfullpath, bsfolder );

			if ( pathtofsref ( bsfolder, &fsr ) == noErr ) {
				
				clearfilespec ( fs );
				
				fs->ref = fsr;
				
				bigstringtofsname ( bsfile, &fs->name );
			
				return ( true );
				}
			}
		
		return ( false );
		
	#endif

	#ifdef WIN95VERSION
	
		copystring (bspath, fsname (fs));

		folderfrompath (bspath, bsfolder);

		if ((isemptystring (bsfolder)) && (! fileisvolume(fs))) {

			filegetdefaultpath (fs);

			pushstring (bspath, fsname (fs));
			}
		
		nullterminate (fsname (fs));
		
		return (true);

	#endif

	} // pathtofilespec