Exemple #1
0
static void
setfile(const char *name, struct stat *fs)
{
	static struct timeval tv[2];

	fs->st_mode &= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;

	TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atim);
	TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtim);
	if (utimes(name, tv))
		cwarn("utimes: %s", name);

	/*
	 * Changing the ownership probably won't succeed, unless we're root
	 * or POSIX_CHOWN_RESTRICTED is not set.  Set uid/gid before setting
	 * the mode; current BSD behavior is to remove all setuid bits on
	 * chown.  If chown fails, lose setuid/setgid bits.
	 */
	if (chown(name, fs->st_uid, fs->st_gid)) {
		if (errno != EPERM)
			cwarn("chown: %s", name);
		fs->st_mode &= ~(S_ISUID|S_ISGID);
	}
	if (chmod(name, fs->st_mode) && errno != EOPNOTSUPP)
		cwarn("chmod: %s", name);

	if (chflags(name, fs->st_flags) && errno != EOPNOTSUPP)
		cwarn("chflags: %s", name);
}
Exemple #2
0
static int  post_preproc(
    char * out
)
/*
 * Convert digraphs and double '\\' of the second byte of SJIS (BIGFIVE or
 * ISO2022_JP).
 * Note: Output of -K option embeds macro informations into comments.
 * scan_token() does not recognize comment and parses it as '/', '*', etc.
 */
{
#if ! HAVE_DIGRAPHS
    int     di_count = 0;
#endif
    int     token_type;
    int     c;
    char *  str;
    char *  cp = out;

    unget_string( out, NULL);
    while ((c = get_ch()) != '\n') {    /* Not to read over to next line    */
        if (char_type[ c] & HSP) {
            *cp++ = c;
            continue;
        }
        str = cp;
        token_type = scan_token( c, &cp, out_wend);
        switch (token_type) {
#if ! MBCHAR_IS_ESCAPE_FREE
        case WSTR   :
        case WCHR   :
            str++;                          /* Skip prefix 'L'      */
            /* Fall through */
        case STR    :
        case CHR    :
            if (bsl_need_escape)
                cp = esc_mbchar( str, cp);
            break;
#endif  /* ! MBCHAR_IS_ESCAPE_FREE  */
#if ! HAVE_DIGRAPHS
        case OPE    :
            if (mcpp_mode == STD && (openum & OP_DIGRAPH)) {
                cp = conv_a_digraph( cp);   /* Convert a digraph    */
                di_count++;
            }
            break;
#endif
        }
    }
    *cp++ = '\n';
    *cp = EOS;
#if ! HAVE_DIGRAPHS
    if (mcpp_mode == STD && di_count && (warn_level & 16))
        cwarn( "%.0s%ld digraph(s) converted"           /* _W16_    */
                , NULL, (long) di_count, NULL);
#endif
    return  0;
}
Exemple #3
0
/*
 * Remove the symbol from the defined list.
 * Called from the #control processor.
 */
void doundef()
{
    int c;

    if (type[(c = skipws())] != LET)
        cerror("Illegal #undef argument", NULLST);
    else
    {
        scanid(c);                          /* Get name to token[]  */
        if (defendel(token, TRUE) == NULL)
        {
#ifdef STRICT_UNDEF
            cwarn("Symbol \"%s\" not defined in #undef", token);
#endif
        }
    }
}
Exemple #4
0
static void
decompress(const char *in, const char *out, int bits)
{
	size_t nr;
	struct stat sb;
	FILE *ifp, *ofp;
	int exists, isreg, oreg;
	u_char buf[1024];

	exists = !stat(out, &sb);
	if (!force && exists && S_ISREG(sb.st_mode) && !permission(out))
		return;
	isreg = oreg = !exists || S_ISREG(sb.st_mode);

	ifp = ofp = NULL;
	if ((ifp = zopen(in, "r", bits)) == NULL) {
		cwarn("%s", in);
		return;
	}
	if (stat(in, &sb)) {
		cwarn("%s", in);
		goto err;
	}
	if (!S_ISREG(sb.st_mode))
		isreg = 0;

	/*
	 * Try to read the first few uncompressed bytes from the input file
	 * before blindly truncating the output file.
	 */
	if ((nr = fread(buf, 1, sizeof(buf), ifp)) == 0) {
		cwarn("%s", in);
		(void)fclose(ifp);
		return;
	}
	if ((ofp = fopen(out, "w")) == NULL ||
	    (nr != 0 && fwrite(buf, 1, nr, ofp) != nr)) {
		cwarn("%s", out);
		(void)fclose(ifp);
		return;
	}

	while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0)
		if (fwrite(buf, 1, nr, ofp) != nr) {
			cwarn("%s", out);
			goto err;
		}

	if (ferror(ifp) || fclose(ifp)) {
		cwarn("%s", in);
		goto err;
	}
	ifp = NULL;

	if (fclose(ofp)) {
		cwarn("%s", out);
		goto err;
	}

	if (isreg) {
		setfile(out, &sb);

		if (unlink(in))
			cwarn("%s", in);
	}
	return;

err:	if (ofp) {
		if (oreg)
			(void)unlink(out);
		(void)fclose(ofp);
	}
	if (ifp)
		(void)fclose(ifp);
}
Exemple #5
0
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);
}
Exemple #6
0
int
dooptions(int argc, char** argv)
/*
 * dooptions is called to process command line arguments (-Detc).
 * It is called only at cpp startup.
 */
{
        register char           *ap;
        register DEFBUF         *dp;
        register int            c;
        int                     i, j;
        char                    *arg;
        SIZES                   *sizp;          /* For -S               */
        int                     size;           /* For -S               */
        int                     isdatum;        /* FALSE for -S*        */
        int                     endtest;        /* For -S               */

        for (i = j = 1; i < argc; i++) {
            arg = ap = argv[i];

            if (*ap++ != '-' || *ap == EOS)
            {
                    argv[j++] = argv[i];
            }
            else {
                c = *ap++;                      /* Option byte          */
                if (islower(c))                 /* Normalize case       */
                    c = toupper(c);
                switch (c) {                    /* Command character    */
                case 'C':                       /* Keep comments        */
                    cflag = TRUE;
                    keepcomments = TRUE;
                    break;

                case 'D':                       /* Define symbol        */
                    /*
                     * If the option is just "-Dfoo", make it -Dfoo=1
                     */
                    while (*ap != EOS && *ap != '=')
                        ap++;
                    if (*ap == EOS)
                        ap = "1";
                    else
                        *ap++ = EOS;
                    /*
                     * Now, save the word and its definition.
                     */
                    dp = defendel(argv[i] + 2, FALSE);
                    dp->repl = savestring(ap);
                    dp->nargs = DEF_NOARGS;
                    break;

                case 'E':                       /* Ignore non-fatal     */
                    eflag = TRUE;               /* errors.              */
                    break;

                case 'I':                       /* Include directory    */
                    AddInclude( ap );           /* BP, 11.09.91 */
                    break;

                case 'N':                       /* No predefineds       */
                    nflag++;                    /* Repeat to undefine   */
                    break;                      /* __LINE__, etc.       */

                case 'S':
                    sizp = size_table;
                    if (0 != (isdatum = (*ap != '*'))) /* If it's just -S,     */
                        endtest = T_FPTR;       /* Stop here            */
                    else {                      /* But if it's -S*      */
                        ap++;                   /* Step over '*'        */
                        endtest = 0;            /* Stop at end marker   */
                    }
                    while (sizp->bits != endtest && *ap != EOS) {
                        if (!isdigit(*ap)) {    /* Skip to next digit   */
                            ap++;
                            continue;
                        }
                        size = 0;               /* Compile the value    */
                        while (isdigit(*ap)) {
                            size *= 10;
                            size += (*ap++ - '0');
                        }
                        if (isdatum)
                            sizp->size = size;  /* Datum size           */
                        else
                            sizp->psize = size; /* Pointer size         */
                        sizp++;
                    }
                    if (sizp->bits != endtest)
                        cwarn("-S, too few values specified in %s", argv[i]);
                    else if (*ap != EOS)
                        cwarn("-S, too many values, \"%s\" unused", ap);
                    break;

                case 'U':                       /* Undefine symbol      */
                    if (defendel(ap, TRUE) == NULL)
                        cwarn("\"%s\" wasn't defined", ap);
                    break;

#if OSL_DEBUG_LEVEL > 1
                case 'X':                       /* Debug                */
                    debug = (isdigit(*ap)) ? atoi(ap) : 1;
#if (HOST == SYS_VMS || HOST == SYS_UNIX)
                    signal(SIGINT, (void (*)(int)) abort); /* Trap "interrupt" */
#endif
                    fprintf(stderr, "Debug set to %d\n", debug);
                    break;
#endif

#if OSL_DEBUG_LEVEL > 1
                case 'P':                       /* #define's dump       */
                    bDumpDefs = 1;
                    fprintf(stderr, "Dump #define's is on\n");
                    break;
#endif

                default:                        /* What is this one?    */
                    cwarn("Unknown option \"%s\"", arg);
                    fprintf(stderr, "The following options are valid:\n\
  -C\t\t\tWrite source file comments to output\n\
  -Dsymbol=value\tDefine a symbol with the given (optional) value\n\
  -Idirectory\t\tAdd a directory to the #include search list\n\
  -N\t\t\tDon't predefine target-specific names\n\
  -Stext\t\tSpecify sizes for #if sizeof\n\
  -Usymbol\t\tUndefine symbol\n");
#if OSL_DEBUG_LEVEL > 1
                    fprintf(stderr, "  -Xvalue\t\tSet internal debug flag\n");
                    fprintf(stderr, "  -P\t\t\tdump #define's\n");
#endif
                    break;
                }                       /* Switch on all options        */
            }                           /* If it's a -option            */
        }                               /* For all arguments            */
#if OSL_DEBUG_LEVEL > 1
        if ( (bDumpDefs ? j > 4 : j > 3) ) {
#else
        if (j > 3) {
#endif
            cerror(
                "Too many file arguments.  Usage: cpp [input [output]]",
                NULLST);
        }
        return (j);                     /* Return new argc              */
}

int
readoptions(char* filename, char*** pfargv)
{
        FILE           *fp;
        int c;
        int bInQuotes = 0;
        char optbuff[1024], *poptbuff;
        int fargc=0, back;
        char *fargv[PARALIMIT], **pfa;

        pfa=*pfargv=malloc(sizeof(fargv));

        poptbuff=&optbuff[0];
        filename++;
        if ((fp = fopen(filename, "r")) == NULL) {
#if OSL_DEBUG_LEVEL > 1
            if ( debug || !bDumpDefs )
                perror(filename);
#endif
            return (FALSE);
        }
        do
        {
            /*
             *  #i27914# double ticks '"' now have a duplicate function:
             *  1. they define a string ( e.g. -DFOO="baz" )
             *  2. a string can contain spaces, so -DFOO="baz zum" defines one
             *  argument no two !
             */
            c=fgetc(fp);
            if ( c != ' ' && c != CR && c != NL && c != HT && c != EOF)
            {
                *poptbuff++=(char)c;
                if( c == '"' )
                    bInQuotes = ~bInQuotes;
            }
            else
            {
                if( c != EOF && bInQuotes )
                    *poptbuff++=(char)c;
                else
                {
                    *poptbuff=EOS;
                    if (strlen(optbuff)>0)
                    {
                        pfa[fargc+1]=malloc(strlen(optbuff)+1);
                        strcpy(pfa[fargc+1],optbuff);
                        fargc++;
                        pfa[fargc+1]=0;
                        poptbuff=&optbuff[0];
                    }
                }
            }
        }
        while ( c != EOF );

        fclose(fp);
        back=dooptions(fargc+1,pfa);

        return (back);
}
Exemple #7
0
static void
compress(const char *in, const char *out, int bits)
{
	size_t nr;
	struct stat isb, sb;
	FILE *ifp, *ofp;
	int exists, isreg, oreg;
	u_char buf[1024];

	exists = !stat(out, &sb);
	if (!force && exists && S_ISREG(sb.st_mode) && !permission(out))
		return;
	isreg = oreg = !exists || S_ISREG(sb.st_mode);

	ifp = ofp = NULL;
	if ((ifp = fopen(in, "r")) == NULL) {
		cwarn("%s", in);
		return;
	}
	if (stat(in, &isb)) {		/* DON'T FSTAT! */
		cwarn("%s", in);
		goto err;
	}
	if (!S_ISREG(isb.st_mode))
		isreg = 0;

	if ((ofp = zopen(out, "w", bits)) == NULL) {
		cwarn("%s", out);
		goto err;
	}
	while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0)
		if (fwrite(buf, 1, nr, ofp) != nr) {
			cwarn("%s", out);
			goto err;
		}

	if (ferror(ifp) || fclose(ifp)) {
		cwarn("%s", in);
		goto err;
	}
	ifp = NULL;

	if (fclose(ofp)) {
		cwarn("%s", out);
		goto err;
	}
	ofp = NULL;

	if (isreg) {
		if (stat(out, &sb)) {
			cwarn("%s", out);
			goto err;
		}

		if (!force && sb.st_size >= isb.st_size) {
			if (verbose)
		(void)fprintf(stderr, "%s: file would grow; left unmodified\n",
		    in);
			eval = 2;
			if (unlink(out))
				cwarn("%s", out);
			goto err;
		}

		setfile(out, &isb);

		if (unlink(in))
			cwarn("%s", in);

		if (verbose) {
			(void)fprintf(stderr, "%s: ", out);
			if (isb.st_size > sb.st_size)
				(void)fprintf(stderr, "%.0f%% compression\n",
				    ((float)sb.st_size / isb.st_size) * 100.0);
			else
				(void)fprintf(stderr, "%.0f%% expansion\n",
				    ((float)isb.st_size / sb.st_size) * 100.0);
		}
	}
	return;

err:	if (ofp) {
		if (oreg)
			(void)unlink(out);
		(void)fclose(ofp);
	}
	if (ifp)
		(void)fclose(ifp);
}
Exemple #8
0
ReturnCode expand(struct Global *global, DEFBUF *tokenp)
{
  /*
   * Expand a macro.  Called from the cpp mainline routine (via subroutine
   * macroid()) when a token is found in the symbol table.  It calls
   * expcollect() to parse actual parameters, checking for the correct number.
   * It then creates a "file" containing a single line containing the
   * macro with actual parameters inserted appropriately.  This is
   * "pushed back" onto the input stream.  (When the get() routine runs
   * off the end of the macro line, it will dismiss the macro itself.)
   */
  int c;
  FILEINFO *file;
  ReturnCode ret=FPP_OK;
      
  /*
   * If no macro is pending, save the name of this macro
   * for an eventual error message.
   */
  if (global->recursion++ == 0)
    global->macro = tokenp;
  else if (global->recursion == RECURSION_LIMIT) {
    cerror(global, ERROR_RECURSIVE_MACRO, tokenp->name, global->macro->name);
    if (global->rec_recover) {
      do {
	c = get(global);
      } while (global->infile != NULL && global->infile->fp == NULL);
      unget(global);
      global->recursion = 0;
      return(FPP_OK);
    }
  }
  /*
   * Here's a macro to expand.
   */
  global->nargs = 0;			/* Formals counter	*/
  global->parmp = global->parm;		/* Setup parm buffer	*/
  switch (tokenp->nargs) {
  case (-2):                              /* __LINE__             */
      if(global->infile->fp)
	  /* This is a file */
	  sprintf(global->work, "%d", global->line);
      else
	  /* This is a macro! Find out the file line number! */
	  for (file = global->infile; file != NULL; file = file->parent) {
	      if (file->fp != NULL) {
		  sprintf(global->work, "%d", file->line);
		  break;
	      }
	  }
      ret=ungetstring(global, global->work);
      if(ret)
	  return(ret);
      break;
    
  case (-3):                              /* __FILE__             */
    for (file = global->infile; file != NULL; file = file->parent) {
      if (file->fp != NULL) {
	sprintf(global->work, "\"%s\"", (file->progname != NULL)
		? file->progname : file->filename);
	ret=ungetstring(global, global->work);
	if(ret)
	  return(ret);
	break;
      }
    }
    break;

  case (-4):				/* __FUNC__ */
    sprintf(global->work, "\"%s\"", global->functionname[0]?
	    global->functionname : "<unknown function>");
    ret=ungetstring(global, global->work);
    if(ret)
	return(ret);
    break;

  case (-5):                              /* __FUNC_LINE__ */
    sprintf(global->work, "%d", global->funcline);
    ret=ungetstring(global, global->work);
    if(ret)
      return(ret);
    break;

  default:
    /*
     * Nothing funny about this macro.
     */
    if (tokenp->nargs < 0) {
      cfatal(global, FATAL_ILLEGAL_MACRO, tokenp->name);
      return(FPP_ILLEGAL_MACRO);
    }
    while ((c = skipws(global)) == '\n')      /* Look for (, skipping */
      global->wrongline = TRUE;		/* spaces and newlines	*/
    if (c != '(') {
      /*
       * If the programmer writes
       *	#define foo() ...
       *	...
       *	foo [no ()]
       * just write foo to the output stream.
       */
      unget(global);
      cwarn(global, WARN_MACRO_NEEDS_ARGUMENTS, tokenp->name);

      /* fputs(tokenp->name, stdout); */
      Putstring(global, tokenp->name);
      return(FPP_OK);
    } else if (!(ret=expcollect(global))) {     /* Collect arguments    */
      if (tokenp->nargs != global->nargs) {     /* Should be an error?  */
	cwarn(global, WARN_WRONG_NUMBER_ARGUMENTS, tokenp->name);
      }
    } else {				/* Collect arguments		*/
      return(ret); /* We failed in argument colleting! */
    }
  case DEF_NOARGS:			/* No parameters just stuffs	*/
    ret=expstuff(global, tokenp->name, tokenp->repl); /* expand macro   */
  }					/* nargs switch 		*/
  return(ret);
}
Exemple #9
0
int dooptions(struct Global *global, struct fppTag *tags)
{
  /*
   * dooptions is called to process command line arguments (-Detc).
   * It is called only at cpp startup.
   */
  DEFBUF *dp;
  char end=FALSE; /* end of taglist */

  while(tags && !end) {
    switch(tags->tag) {
    case FPPTAG_END:
      end=TRUE;
      break;
    case FPPTAG_INITFUNC:
      global->initialfunc = (char *) tags->data;
      break;
    case FPPTAG_DISPLAYFUNCTIONS:
      global->outputfunctions = TRUEFALSE(tags->data);
      break;
    case FPPTAG_RIGHTCONCAT:
      global->rightconcat = TRUEFALSE(tags->data);
      break;
    case FPPTAG_OUTPUTMAIN:
      global->outputfile = TRUEFALSE(tags->data);
      break;
    case FPPTAG_NESTED_COMMENTS:
      global->nestcomments = TRUEFALSE(tags->data);
      break;
    case FPPTAG_WARNMISSINCLUDE:
      global->warnnoinclude = TRUEFALSE(tags->data);
      break;
    case FPPTAG_WARN_NESTED_COMMENTS:
      global->warnnestcomments = TRUEFALSE(tags->data);
      break;
    case FPPTAG_OUTPUTSPACE:
      global->showspace = TRUEFALSE(tags->data);
      break;
    case FPPTAG_OUTPUTBALANCE:
      global->showbalance = TRUEFALSE(tags->data);
      break;
    case FPPTAG_OUTPUTINCLUDES:
      global->showincluded = TRUEFALSE(tags->data);
      break;
    case FPPTAG_IGNOREVERSION:
      global->showversion = TRUEFALSE(tags->data);
      break;
    case FPPTAG_WARNILLEGALCPP:
      global->warnillegalcpp=TRUEFALSE(tags->data);
      break;
    case FPPTAG_OUTPUTLINE:
      global->outputLINE= TRUEFALSE(tags->data);
      break;
    case FPPTAG_KEEPCOMMENTS:
      if(tags->data) {
	global->cflag = TRUE;
	global->keepcomments = TRUE;
      }
      break;
    case FPPTAG_DEFINE:
      /*
       * If the option is just "-Dfoo", make it -Dfoo=1
       */
      {
	char *symbol=(char *)tags->data;
	char *text=symbol;
	while (*text != EOS && *text != '=')
	  text++;
	if (*text == EOS)
	  text = "1";
	else
	  *text++ = EOS;
	/*
	 * Now, save the word and its definition.
	 */
	dp = defendel(global, symbol, FALSE);
	if(!dp)
	  return(FPP_OUT_OF_MEMORY);
	dp->repl = savestring(global, text);
	dp->nargs = DEF_NOARGS;
      }
      break;
    case FPPTAG_IGNORE_NONFATAL:
      global->eflag = TRUE;
      break;
    case FPPTAG_INCLUDE_DIR:
      if (global->incend >= &global->incdir[NINCLUDE]) {
	  cfatal(global, FATAL_TOO_MANY_INCLUDE_DIRS);
	  return(FPP_TOO_MANY_INCLUDE_DIRS);
      }
      *global->incend++ = (char *)tags->data;
      break;
    case FPPTAG_INCLUDE_FILE:
    case FPPTAG_INCLUDE_MACRO_FILE:
      if (global->included >= NINCLUDE) {
	  cfatal(global, FATAL_TOO_MANY_INCLUDE_FILES);
	  return(FPP_TOO_MANY_INCLUDE_FILES);
      }
      global->include[global->included] = (char *)tags->data;

      global->includeshow[global->included] =
	  (tags->tag == FPPTAG_INCLUDE_FILE);

      global->included++;
      break;
    case FPPTAG_BUILTINS:
      global->nflag|=(tags->data?NFLAG_BUILTIN:0);
      break;
    case FPPTAG_PREDEFINES:
      global->nflag|=(tags->data?NFLAG_PREDEFINE:0);
      break;
    case FPPTAG_IGNORE_CPLUSPLUS:
      global->cplusplus=!tags->data;
      break;
    case FPPTAG_SIZEOF_TABLE:
      {
	SIZES *sizp;	/* For -S		*/
	int size;	/* For -S		*/
	int isdatum;	/* FALSE for -S*	*/
	int endtest;	/* For -S		*/

	char *text=(char *)tags->data;

	sizp = size_table;
	if (isdatum = (*text != '*')) /* If it's just -S,     */
	  endtest = T_FPTR;	/* Stop here		*/
	else {			/* But if it's -S*      */
	  text++;		/* Step over '*'        */
	  endtest = 0;		/* Stop at end marker	*/
	}
	while (sizp->bits != endtest && *text != EOS) {
	  if (!isdigit(*text)) {    /* Skip to next digit   */
	    text++;
	    continue;
	  }
	  size = 0;		/* Compile the value	*/
	  while (isdigit(*text)) {
	    size *= 10;
	    size += (*text++ - '0');
	  }
	  if (isdatum)
	    sizp->size = size;	/* Datum size		*/
	  else
	    sizp->psize = size; /* Pointer size 	*/
	  sizp++;
	}
	if (sizp->bits != endtest)
	  cwarn(global, WARN_TOO_FEW_VALUES_TO_SIZEOF, NULL);
	else if (*text != EOS)
	  cwarn(global, WARN_TOO_MANY_VALUES_TO_SIZEOF, NULL);
      }
      break;
    case FPPTAG_UNDEFINE:
      if (defendel(global, (char *)tags->data, TRUE) == NULL)
	cwarn(global, WARN_NOT_DEFINED, tags->data);
      break;
    case FPPTAG_OUTPUT_DEFINES:
      global->wflag++;
      break;
    case FPPTAG_INPUT_NAME:
      strcpy(global->work, tags->data);    /* Remember input filename */
      global->first_file=tags->data;
      break;
    case FPPTAG_INPUT:
      global->input=(char *(*)(char *, int, void *))tags->data;
      break;
    case FPPTAG_OUTPUT:
      global->output=(void (*)(int, void *))tags->data;
      break;      
    case FPPTAG_ERROR:
      global->error=(void (*)(void *, char *, va_list))tags->data;
      break;
    case FPPTAG_USERDATA:
      global->userdata=tags->data;
      break;
    case FPPTAG_LINE:
      global->linelines= TRUEFALSE(tags->data);
      break;
    case FPPTAG_EXCLFUNC:
      global->excludedinit[ global->excluded++ ] = (char *)tags->data;
      break;
    default:
      cwarn(global, WARN_INTERNAL_ERROR, NULL);
      break;
    }
    tags++;
  }
  return(0);
}
Exemple #10
0
/*
 * Expand a macro.  Called from the cpp mainline routine (via subroutine
 * macroid()) when a token is found in the symbol table.  It calls
 * expcollect() to parse actual parameters, checking for the correct number.
 * It then creates a "file" containing a single line containing the
 * macro with actual parameters inserted appropriately.  This is
 * "pushed back" onto the input stream.  (When the get() routine runs
 * off the end of the macro line, it will dismiss the macro itself.)
 */
void expand(DEFBUF* tokenp)
{
    int c;
    FILEINFO* file;

#if OSL_DEBUG_LEVEL > 1
    if (debug)
        dumpadef("expand entry", tokenp);
#endif
    /*
     * If no macro is pending, save the name of this macro
     * for an eventual error message.
     */
    if (recursion++ == 0)
        macro = tokenp;
    else if (recursion == RECURSION_LIMIT)
    {
        cerror("Recursive macro definition of \"%s\"", tokenp->name);
        fprintf(stderr, "(Defined by \"%s\")\n", macro->name);
        if (rec_recover)
        {
            do
            {
                c = get();
            }
            while (infile != NULL && infile->fp == NULL);
            unget();
            recursion = 0;
            return;
        }
    }
    /*
     * Here's a macro to expand.
     */
    nargs = 0;                              /* Formals counter      */
    parmp = parm;                           /* Setup parm buffer    */
    switch (tokenp->nargs)
    {
    case (-2):                              /* __LINE__             */
        sprintf(work, "%d", line);
        ungetstring(work);
        break;

    case (-3):                              /* __FILE__             */
        for (file = infile; file != NULL; file = file->parent)
        {
            if (file->fp != NULL)
            {
                sprintf(work, "\"%s\"", (file->progname != NULL)
                        ? file->progname : file->filename);
                ungetstring(work);
                break;
            }
        }
        break;

    default:
        /*
         * Nothing funny about this macro.
         */
        if (tokenp->nargs < 0)
            cfatal("Bug: Illegal __ macro \"%s\"", tokenp->name);
        while ((c = skipws()) == '\n')      /* Look for (, skipping */
            wrongline = TRUE;               /* spaces and newlines  */
        if (c != '(')
        {
            /*
             * If the programmer writes
             *      #define foo() ...
             *      ...
             *      foo [no ()]
             * just write foo to the output stream.
             */
            unget();
            cwarn("Macro \"%s\" needs arguments", tokenp->name);
            fputs(tokenp->name, pCppOut );
            return;
        }
        else if (expcollect())              /* Collect arguments    */
        {
            if (tokenp->nargs != nargs)     /* Should be an error?  */
            {
                cwarn("Wrong number of macro arguments for \"%s\"",
                      tokenp->name);
            }
#if OSL_DEBUG_LEVEL > 1
            if (debug)
                dumpparm("expand");
#endif
        }                           /* Collect arguments            */
    case DEF_NOARGS:                /* No parameters just stuffs    */
        expstuff(tokenp);           /* Do actual parameters         */
    }                               /* nargs switch                 */
}
Exemple #11
0
/*
 * Called from control when a #define is scanned.  This module
 * parses formal parameters and the replacement string.  When
 * the formal parameter name is encountered in the replacement
 * string, it is replaced by a character in the range 128 to
 * 128+NPARAM (this allows up to 32 parameters within the
 * Dec Multinational range).
 *
 * There is some special case code to distinguish
 *      #define foo     bar
 * from #define foo()   bar
 *
 * Also, we make sure that
 *      #define foo     foo
 * expands to "foo" but doesn't put cpp into an infinite loop.
 *
 * A warning message is printed if you redefine a symbol to a
 * different text.  I.e,
 *      #define foo     123
 *      #define foo     123
 * is ok, but
 *      #define foo     123
 *      #define foo     +123
 * is not.
 *
 * The following subroutines are called from define():
 * checkparm    called when a token is scanned.  It checks through the
 *              array of formal parameters.  If a match is found, the
 *              token is replaced by a control byte which will be used
 *              to locate the parameter when the macro is expanded.
 * textput      puts a string in the macro work area (parm[]), updating
 *              parmp to point to the first free byte in parm[].
 *              textput() tests for work buffer overflow.
 * charput      puts a single character in the macro work area (parm[])
 *              in a manner analogous to textput().
 */
void dodefine()
{
    int c;
    DEFBUF* dp;            /* -> new definition    */
    int isredefine;        /* TRUE if redefined    */
    char* old = NULL;         /* Remember redefined   */

    if (type[(c = skipws())] != LET)
        goto bad_define;
    isredefine = FALSE;                     /* Set if redefining    */
    if ((dp = lookid(c)) == NULL)           /* If not known now     */
        dp = defendel(token, FALSE);        /* Save the name        */
    else                                    /* It's known:          */
    {
        isredefine = TRUE;                  /* Remember this fact   */
        old = dp->repl;                     /* Remember replacement */
        dp->repl = NULL;                    /* No replacement now   */
    }
    parlist[0] = parmp = parm;              /* Setup parm buffer    */
    if ((c = get()) == '(')                 /* With arguments?      */
    {
        nargs = 0;                          /* Init formals counter */
        do                                  /* Collect formal parms */
        {
            if (nargs >= LASTPARM)
                cfatal("Too many arguments for macro", NULLST);
            else if ((c = skipws()) == ')')
                break;                      /* Got them all         */
            else if (type[c] != LET)        /* Bad formal syntax    */
                goto bad_define;
            scanid(c);                      /* Get the formal param */
            parlist[nargs++] = parmp;       /* Save its start       */
            textput(token);                 /* Save text in parm[]  */
        }
        while ((c = skipws()) == ',');      /* Get another argument */
        if (c != ')')                       /* Must end at )        */
            goto bad_define;
        c = ' ';                            /* Will skip to body    */
    }
    else
    {
        /*
         * DEF_NOARGS is needed to distinguish between
         * "#define foo" and "#define foo()".
         */
        nargs = DEF_NOARGS;                 /* No () parameters     */
    }
    if (type[c] == SPA)                     /* At whitespace?       */
        c = skipws();                       /* Not any more.        */
    workp = work;                           /* Replacement put here */
    inmacro = TRUE;                         /* Keep \<newline> now  */
    while (c != EOF_CHAR && c != '\n')      /* Compile macro body   */
    {
        if (c == '#')                       /* Token concatenation? */
        {
            while (workp > work && type[(int)workp[-1]] == SPA)
                --workp;                    /* Erase leading spaces */
            save(TOK_SEP);                  /* Stuff a delimiter    */
            c = skipws();                   /* Eat whitespace       */
            if (type[c] == LET)             /* Another token here?  */
                ;                           /* Stuff it normally    */
            else if (type[c] == DIG)        /* Digit string after?  */
            {
                while (type[c] == DIG)      /* Stuff the digits     */
                {
                    save(c);
                    c = get();
                }
                save(TOK_SEP);              /* Delimit 2nd token    */
            }
            else
            {
                ciwarn("Strange character after # (%d.)", c);
            }
            continue;
        }
        switch (type[c])
        {
        case LET:
            checkparm(c, dp);               /* Might be a formal    */
            break;

        case DIG:                           /* Number in mac. body  */
        case DOT:                           /* Maybe a float number */
            scannumber(c, save);            /* Scan it off          */
            break;

        case QUO:                           /* String in mac. body  */
            stparmscan(c);
            break;

        case BSH:                           /* Backslash            */
            save('\\');
            if ((c = get()) == '\n')
                wrongline = TRUE;
            save(c);
            break;

        case SPA:                           /* Absorb whitespace    */
            /*
             * Note: the "end of comment" marker is passed on
             * to allow comments to separate tokens.
             */
            if (workp[-1] == ' ')           /* Absorb multiple      */
                break;                      /* spaces               */
            else if (c == '\t')
                c = ' ';                    /* Normalize tabs       */
            /* Fall through to store character                      */
        default:                            /* Other character      */
            save(c);
            break;
        }
        c = get();
    }
    inmacro = FALSE;                        /* Stop newline hack    */
    unget();                                /* For control check    */
    if (workp > work && workp[-1] == ' ')   /* Drop trailing blank  */
        workp--;
    *workp = EOS;                           /* Terminate work       */
    dp->repl = savestring(work);            /* Save the string      */
    dp->nargs = nargs;                      /* Save arg count       */
#if OSL_DEBUG_LEVEL > 1
    if (debug)
        dumpadef("macro definition", dp);
    else if (bDumpDefs)
        dumpadef(NULL, dp);
#endif
    if (isredefine)                         /* Error if redefined   */
    {
        if ((old != NULL && dp->repl != NULL && !streq(old, dp->repl)) ||
            (old == NULL && dp->repl != NULL) ||
            (old != NULL && dp->repl == NULL))
        {
#ifdef STRICT_UNDEF
            cerror("Redefining defined variable \"%s\"", dp->name);
#else
            cwarn("Redefining defined variable \"%s\"", dp->name);
#endif
        }
        if (old != NULL)                    /* We don't need the    */
            free(old);                      /* old definition now.  */
    }
    return;

  bad_define:
    cerror("#define syntax error", NULLST);
    inmacro = FALSE;                        /* Stop <newline> hack  */
}
Exemple #12
0
/*
 * dooptions is called to process command line arguments (-Detc).
 * It is called only at cpp startup.
 */
int dooptions(int argc, char** argv)
{
    char* ap;
    DEFBUF* dp;
    int c;
    int i, j;
    char* arg;
    SIZES* sizp;        /* For -S               */
    int size;           /* For -S               */
    int isdatum;        /* FALSE for -S*        */
    int endtest;        /* For -S               */

    for (i = j = 1; i < argc; i++)
    {
        arg = ap = argv[i];

        if (*ap++ != '-' || *ap == EOS)
        {
            argv[j++] = argv[i];
        }
        else
        {
            c = *ap++;                      /* Option byte          */
            if (islower(c))                 /* Normalize case       */
                c = toupper(c);
            switch (c)                      /* Command character    */
            {
            case 'C':                       /* Keep comments        */
                cflag = TRUE;
                keepcomments = TRUE;
                break;

            case 'D':                       /* Define symbol        */
                /*
                 * If the option is just "-Dfoo", make it -Dfoo=1
                 */
                while (*ap != EOS && *ap != '=')
                    ap++;
                if (*ap == EOS)
                    ap = "1";
                else
                    *ap++ = EOS;
                /*
                 * Now, save the word and its definition.
                 */
                dp = defendel(argv[i] + 2, FALSE);
                dp->repl = savestring(ap);
                dp->nargs = DEF_NOARGS;
                break;

            case 'E':                       /* Ignore non-fatal     */
                eflag = TRUE;               /* errors.              */
                break;

            case 'I':                       /* Include directory    */
                AddInclude( ap );           /* BP, 11.09.91 */
                break;

            case 'N':                       /* No predefineds       */
                nflag++;                    /* Repeat to undefine   */
                break;                      /* __LINE__, etc.       */

            case 'S':
                sizp = size_table;
                if (0 != (isdatum = (*ap != '*'))) /* If it's just -S,     */
                    endtest = T_FPTR;       /* Stop here            */
                else                        /* But if it's -S*      */
                {
                    ap++;                   /* Step over '*'        */
                    endtest = 0;            /* Stop at end marker   */
                }
                while (sizp->bits != endtest && *ap != EOS)
                {
                    if (!isdigit(*ap))      /* Skip to next digit   */
                    {
                        ap++;
                        continue;
                    }
                    size = 0;               /* Compile the value    */
                    while (isdigit(*ap))
                    {
                        size *= 10;
                        size += (*ap++ - '0');
                    }
                    if (isdatum)
                        sizp->size = size;  /* Datum size           */
                    else
                        sizp->psize = size; /* Pointer size         */
                    sizp++;
                }
                if (sizp->bits != endtest)
                    cwarn("-S, too few values specified in %s", argv[i]);
                else if (*ap != EOS)
                    cwarn("-S, too many values, \"%s\" unused", ap);
                break;

            case 'U':                       /* Undefine symbol      */
                if (defendel(ap, TRUE) == NULL)
                    cwarn("\"%s\" wasn't defined", ap);
                break;

#if OSL_DEBUG_LEVEL > 1
            case 'X':                       /* Debug                */
                debug = (isdigit(*ap)) ? atoi(ap) : 1;
#if (HOST == SYS_UNIX)
                signal(SIGINT, (void (*)(int)) abort); /* Trap "interrupt" */
#endif
                fprintf(stderr, "Debug set to %d\n", debug);
                break;
#endif

#if OSL_DEBUG_LEVEL > 1
            case 'P':                       /* #define's dump       */
                bDumpDefs = 1;
                fprintf(stderr, "Dump #define's is on\n");
                break;
#endif

            default:                        /* What is this one?    */
                cwarn("Unknown option \"%s\"", arg);
                fprintf(stderr, "The following options are valid:\n\
  -C\t\t\tWrite source file comments to output\n\
  -Dsymbol=value\tDefine a symbol with the given (optional) value\n\
  -Idirectory\t\tAdd a directory to the #include search list\n\
  -N\t\t\tDon't predefine target-specific names\n\
  -Stext\t\tSpecify sizes for #if sizeof\n\
  -Usymbol\t\tUndefine symbol\n");
#if OSL_DEBUG_LEVEL > 1
                fprintf(stderr, "  -Xvalue\t\tSet internal debug flag\n");
                fprintf(stderr, "  -P\t\t\tdump #define's\n");
#endif
                break;
            }                       /* Switch on all options        */
        }                           /* If it's a -option            */
    }                               /* For all arguments            */
#if OSL_DEBUG_LEVEL > 1
    if ( (bDumpDefs ? j > 4 : j > 3) )
#else
    if (j > 3)
#endif
    {
        cerror( "Too many file arguments.  Usage: cpp [input [output]]",
                NULLST);
    }
    return (j);                     /* Return new argc              */
}
Exemple #13
0
int fppPreProcess(struct fppTag *tags)
{
  int i=0;
  ReturnCode ret;       /* cpp return code */
  struct Global *global;

  global=(struct Global *)malloc(sizeof(struct Global));
  if(!global)
    return(FPP_OUT_OF_MEMORY);

  memset(global, 0, sizeof(struct Global));

  global->infile=NULL;
  global->line=0;
  global->wrongline=0;
  global->errors=0;
  global->recursion=0;
  global->rec_recover=TRUE;
  global->instring=FALSE;
  global->inmacro=FALSE;
  global->workp=NULL;
  global->keepcomments = FALSE;  /* Write out comments flag     */
  global->cflag = FALSE;          /* -C option (keep comments)    */
  global->eflag = FALSE;          /* -E option (never fail)       */
  global->nflag = 0;              /* -N option (no predefines)    */
  global->wflag = FALSE;          /* -W option (write #defines)   */

  global->ifstack[0]=TRUE;       /* #if information     */
  global->ifptr = global->ifstack;
  global->incend = global->incdir;

  /* names defined at cpp start */
  global->preset[0]="frexxcpp"; /* This is the Frexx cpp program */
#if defined( unix )
  global->preset[1]="unix";
  global->preset[2]= NULL;
#endif

  /* Note: order is important   */
  global->magic[0] = "__LINE__";
  global->magic[1] = "__FILE__";
  global->magic[2] = "__FUNCTION__";
  global->magic[3] = "__FUNC_LINE__";
  global->magic[4] = NULL;                        /* Must be last       */

  global->funcline = 0;

  global->cplusplus=1;
  global->sharpfilename=NULL;

  global->parmp=NULL;
  global->nargs=0;

  global->macro=NULL;
  global->evalue=0;

  global->error=NULL;
  global->first_file=NULL;

  global->linelines=TRUE;
  global->warnillegalcpp = FALSE;
  global->outputLINE = TRUE;
  global->warnnoinclude = TRUE;
  global->showversion = TRUE;
  global->showincluded = FALSE;
  global->showspace = FALSE;
  global->nestcomments = FALSE;
  global->warnnestcomments = FALSE;
  global->outputfile = TRUE;
  global->included = 0;

  global->comment = FALSE;
  global->rightconcat = FALSE;
  global->work[0] = '\0';
  global->initialfunc = NULL;

  memset(global->symtab, 0, SBSIZE * sizeof(DEFBUF *));

  ret=initdefines(global);  /* O.S. specific def's  */
  if(ret)
    return(ret);
  dooptions(global, tags);  /* Command line -flags  */
  ret=addfile(global, global->inputio, global->work); /* "open" main input file       */

  global->out = global->outputfile;

  if(!ret)
    ret=cppmain(global);             /* Process main file            */
  if ((i = (int)(global->ifptr - global->ifstack)) != 0) {
#if OLD_PREPROCESSOR
    cwarn(global, ERROR_IFDEF_DEPTH, i);
#else
    cerror(global, ERROR_IFDEF_DEPTH, i);
#endif
  }

  if (global->errors > 0 && !global->eflag)
    return(IO_ERROR);
  return(IO_NORMAL);       /* No errors or -E option set   */
}
Exemple #14
0
int
control(int counter)
/*
 * Process #control lines.  Simple commands are processed inline,
 * while complex commands have their own subroutines.
 *
 * The counter is used to force out a newline before #line, and
 * #pragma commands.  This prevents these commands from ending up at
 * the end of the previous line if cpp is invoked with the -C option.
 */
{
        register int            c;
        register char           *tp;
        register int            hash;
        char                    *ep;

        c = skipws();
        if (c == '\n' || c == EOF_CHAR)
            return (counter + 1);
        if (!isdigit(c))
            scanid(c);                  /* Get #word to token[]         */
        else {
            unget();                    /* Hack -- allow #123 as a      */
            strcpy(token, "line");      /* synonym for #line 123        */
        }
        hash = (token[1] == EOS) ? L_nogood : (token[0] + (token[2] << 1));
        switch (hash) {
        case L_assert:  tp = "assert";          break;
        case L_define:  tp = "define";          break;
        case L_elif:    tp = "elif";            break;
        case L_else:    tp = "else";            break;
        case L_endif:   tp = "endif";           break;
        case L_if:      tp = "if";              break;
        case L_ifdef:   tp = "ifdef";           break;
        case L_ifndef:  tp = "ifndef";          break;
        case L_include: tp = "include";         break;
        case L_line:    tp = "line";            break;
        case L_pragma:  tp = "pragma";          break;
        case L_undef:   tp = "undef";           break;
        case L_error:   tp = "error";           break;
#if OSL_DEBUG_LEVEL > 1
        case L_debug:   tp = "debug";           break;
        case L_nodebug: tp = "nodebug";         break;
#endif
        default:        hash = L_nogood;
        case L_nogood:  tp = "";                break;
        }
        if (!streq(tp, token))
            hash = L_nogood;
        /*
         * hash is set to a unique value corresponding to the
         * control keyword (or L_nogood if we think it's nonsense).
         */
        if (infile->fp == NULL)
            cwarn("Control line \"%s\" within macro expansion", token);
        if (!compiling) {                       /* Not compiling now    */
            switch (hash) {
            case L_if:                          /* These can't turn     */
            case L_ifdef:                       /*  compilation on, but */
            case L_ifndef:                      /*   we must nest #if's */
                if (++ifptr >= &ifstack[BLK_NEST])
                    goto if_nest_err;
                *ifptr = 0;                     /* !WAS_COMPILING       */
            case L_line:                        /* Many                 */
            /*
             * Are pragma's always processed?
             */
            case L_pragma:                      /*  options             */
            case L_include:                     /*   are uninteresting  */
            case L_define:                      /*    if we             */
            case L_undef:                       /*     aren't           */
            case L_assert:                      /*      compiling.      */
            case L_error:                       /* BP 5.3.92, #error */
dump_line:      skipnl();                       /* Ignore rest of line  */
                return (counter + 1);
            }
        }
        /*
         * Make sure that #line and #pragma are output on a fresh line.
         */
        if (counter > 0 && (hash == L_line || hash == L_pragma)) {
            PUTCHAR('\n');
            counter--;
        }
        switch (hash) {
        case L_line:
            /*
             * Parse the line to update the line number and "progname"
             * field and line number for the next input line.
             * Set wrongline to force it out later.
             */
            c = skipws();
            workp = work;                       /* Save name in work    */
            while (c != '\n' && c != EOF_CHAR) {
                save(c);
                c = get();
            }
            unget();
            save(EOS);
            /*
             * Split #line argument into <line-number> and <name>
             * We subtract 1 as we want the number of the next line.
             */
            line = atoi(work) - 1;              /* Reset line number    */
            for (tp = work; isdigit(*tp) || type[(int)*tp] == SPA; tp++)
                ;                               /* Skip over digits     */
            if (*tp != EOS) {                   /* Got a filename, so:  */
                if (*tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL) {
                    tp++;                       /* Skip over left quote */
                    *ep = EOS;                  /* And ignore right one */
                }
                if (infile->progname != NULL)   /* Give up the old name */
                    free(infile->progname);     /* if it's allocated.   */
                infile->progname = savestring(tp);
            }
            wrongline = TRUE;                   /* Force output later   */
            break;

        case L_include:
            doinclude();
            break;

        case L_define:
            dodefine();
            break;

        case L_undef:
            doundef();
            break;

        case L_else:
            if (ifptr == &ifstack[0])
                goto nest_err;
            else if ((*ifptr & ELSE_SEEN) != 0)
                goto else_seen_err;
            *ifptr |= ELSE_SEEN;
            if ((*ifptr & WAS_COMPILING) != 0) {
                if (compiling || (*ifptr & TRUE_SEEN) != 0)
                    compiling = FALSE;
                else {
                    compiling = TRUE;
                }
            }
            break;

        case L_elif:
            if (ifptr == &ifstack[0])
                goto nest_err;
            else if ((*ifptr & ELSE_SEEN) != 0) {
else_seen_err:  cerror("#%s may not follow #else", token);
                goto dump_line;
            }
            if ((*ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING) {
                compiling = FALSE;              /* Done compiling stuff */
                goto dump_line;                 /* Skip this clause     */
            }
            doif(L_if);
            break;

        case L_if:
        case L_ifdef:
        case L_ifndef:
            if (++ifptr >= &ifstack[BLK_NEST])
if_nest_err:    cfatal("Too many nested #%s statements", token);
            *ifptr = WAS_COMPILING;
            doif(hash);
            break;

        case L_endif:
            if (ifptr == &ifstack[0]) {
nest_err:       cerror("#%s must be in an #if", token);
                goto dump_line;
            }
            if (!compiling && (*ifptr & WAS_COMPILING) != 0)
                wrongline = TRUE;
            compiling = ((*ifptr & WAS_COMPILING) != 0);
            --ifptr;
            break;

        case L_assert:
            if (eval() == 0)
                cerror("Preprocessor assertion failure", NULLST);
            break;

        case L_pragma:
            /*
             * #pragma is provided to pass "options" to later
             * passes of the compiler.  cpp doesn't have any yet.
             */
            fprintf( pCppOut, "#pragma ");
            while ((c = get()) != '\n' && c != EOF_CHAR)
                cput(c);
            unget();
            break;

#if OSL_DEBUG_LEVEL > 1
        case L_debug:
            if (debug == 0)
                dumpdef("debug set on");
            debug++;
            break;

        case L_nodebug:
            debug--;
            break;
#endif
        case L_error:                       /* BP 5.3.92, #error */
        {
            fprintf( pCppOut, "cpp: line %u, Error directive: ", line );
            while ((c = get()) != '\n' && c != EOF_CHAR)
                cput(c);
            fprintf( pCppOut, "\n" );
            exit( 1 );
            break;
        }
        default:
            /*
             * Undefined #control keyword.
             * Note: the correct behavior may be to warn and
             * pass the line to a subsequent compiler pass.
             * This would allow #asm or similar extensions.
             */
            cerror("Illegal # command \"%s\"", token);
            break;
        }
        if (hash != L_include) {
#if OLD_PREPROCESSOR
            /*
             * Ignore the rest of the #control line so you can write
             *          #if     foo
             *          #endif  foo
             */
            goto dump_line;                     /* Take common exit     */
#else
            if (skipws() != '\n') {
                cwarn("Unexpected text in #control line ignored", NULLST);
                skipnl();
            }
#endif
        }
        return (counter + 1);
}
Exemple #15
0
int main (int argc, char **argv) {
	int i;
	struct stat sb;
	void * addr;
	rec *r, *e;
	struct tm *tmp;
	char fmt[1024];
	
	/*
	std::map<int, cnt*> hstat;
	std::map<int, cnt*> dstat;
	cnt *ac = new cnt();
	std::map<int, cnt*>::iterator it;
	std::map<int, int>::iterator ii;
	*/
	
	std::tr1::unordered_map<int, cnt*> hstat;
	std::tr1::unordered_map<int, cnt*> dstat;
	cnt *ac = new cnt();
	std::tr1::unordered_map<int, cnt*>::iterator it;
	std::tr1::unordered_map<int, int>::iterator ii;
	
	for (i=1; i<argc; i++) {
		cwarn("%s",argv[i]);
		int fd = open(argv[i], O_RDONLY);
		if (fd == -1) die("open %s failed: %s",argv[i],strerror(errno));
		if (fstat(fd, &sb) == -1) die("fstat %s failed: %s",argv[i],strerror(errno));
		cwarn("fd = %d, size: %zd",fd, sb.st_size);
		
		addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE,fd, 0);
		if (addr == MAP_FAILED) die("mmap failed: %s",strerror(errno));
		r = (rec *) addr;
		e = (rec *)((char *)addr + sb.st_size);
		int count = 0;
		int cur_day = 0,cur_hour = 0;
		while (r < e) {
			time_t time = r->ts;
			int ua = r->ua > AGENTS-1 ? 0xffffffff : r->ua;
			tmp = localtime( &time );
			
			strftime(fmt,1024,"%Y%m%d",tmp);
			int day_id = atoi(fmt);
			strftime(fmt,1024,"%Y%m%d%H",tmp);
			int hour_id = atoi(fmt);
			
			cnt *hc,*dc;
			if (!( hc = hstat[hour_id] ) ) hc = hstat[hour_id] = new cnt();
			if (!( dc = dstat[day_id] ) ) dc = dstat[day_id] = new cnt();
			
			hc->hits++;
			hc->users[ r->uid ]++;
			hc->agent[ua][ r->uid ]++;
			
			dc->hits++;
			dc->users[ r->uid ]++;
			dc->agent[ua][ r->uid ]++;
			
			ac->hits++;
			ac->users[ r->uid ]++;
			ac->agent[ua][ r->uid ]++;
			
			r++;
		}
	}
	
	printf("day/hour\tnon\tios\tand\twin\tmac\tlin\twww\tunk\thits\tusers\n");
	for( it = hstat.begin(); it!= hstat.end(); ++it) {
		printf("%-16d", (*it).first);
		for (i=0; i<AGENTS; i++) {
			printf("%d\t",(*it).second->agent[i].size());
		}
		printf("%d\t",(*it).second->hits);
		printf("%d\t",(*it).second->users.size());
		printf("\n");
	}
	
	return 0;
}
Exemple #16
0
ReturnCode control( struct Global *global,
    int *counter )  /* Pending newline counter */
{
    /*
     * Process #control lines.  Simple commands are processed inline,
     * while complex commands have their own subroutines.
     *
     * The counter is used to force out a newline before #line, and
     * #pragma commands.  This prevents these commands from ending up at
     * the end of the previous line if cpp is invoked with the -C option.
     */

    int c;
    char *tp;
    int hash;
    char *ep;
    ReturnCode ret;

    c = skipws( global );

    if( c == '\n' || c == EOF_CHAR )
        {
        (*counter)++;

        return(FPP_OK);
        }

    if( !isdigit(c) )
        scanid( global, c );                  /* Get #word to tokenbuf        */
    else
        {
        unget( global );                    /* Hack -- allow #123 as a      */

        strcpy( global->tokenbuf, "line" );   /* synonym for #line 123        */
        }

    hash = (global->tokenbuf[1] == EOS) ? L_nogood : (global->tokenbuf[0] + (global->tokenbuf[2] << 1));

    switch( hash )
        {
        case L_assert:
            tp = "assert";
            break;
        case L_define:
            tp = "define";
            break;
        case L_elif:
            tp = "elif";
            break;
        case L_else:
            tp = "else";
            break;
        case L_endif:
            tp = "endif";
            break;
        case L_error:
            tp = "error";
            break;
        case L_if:
            tp = "if";
            break;
        case L_ifdef:
            tp = "ifdef";
            break;
        case L_ifndef:
            tp = "ifndef";
            break;
        case L_include:
            tp = "include";
            break;
        case L_line:
            tp = "line";
            break;
        case L_pragma:
            tp = "pragma";
            break;
        case L_undef:
            tp = "undef";
            break;
        default:
            hash = L_nogood;
        case L_nogood:
            tp = "";
            break;
        }

    if( !streq( tp, global->tokenbuf ) )
        hash = L_nogood;

    /*
     * hash is set to a unique value corresponding to the
     * control keyword (or L_nogood if we think it's nonsense).
     */
    if( global->infile->fp == NULL )
        cwarn( global, WARN_CONTROL_LINE_IN_MACRO, global->tokenbuf );

    if( !compiling )
        {                       /* Not compiling now    */
        switch( hash )
            {
            case L_if:              /* These can't turn     */
            case L_ifdef:           /*  compilation on, but */
            case L_ifndef:          /*   we must nest #if's */
                if( ++global->ifptr >= &global->ifstack[BLK_NEST] )
                    {
                    cfatal( global, FATAL_TOO_MANY_NESTINGS, global->tokenbuf );

                    return( FPP_TOO_MANY_NESTED_STATEMENTS );
                    }

                *global->ifptr = 0;       /* !WAS_COMPILING   */

            case L_line:            /* Many         */
                /*
                 * Are pragma's always processed?
                 */
            case L_pragma:          /*  options     */
            case L_include:         /*   are uninteresting  */
            case L_define:          /*    if we     */
            case L_undef:           /*     aren't           */
            case L_assert:          /*  compiling.  */
            case L_error:
                dump_line( global, counter );       /* Ignore rest of line  */
                return(FPP_OK);
            }
        }
    /*
     * Make sure that #line and #pragma are output on a fresh line.
     */
    if( *counter > 0 && (hash == L_line || hash == L_pragma) )
        {
        Putchar( global, '\n' );

        (*counter)--;
        }

    switch( hash )
        {
        case L_line:
            /*
             * Parse the line to update the line number and "progname"
             * field and line number for the next input line.
             * Set wrongline to force it out later.
             */
            c = skipws( global );

            global->workp = global->work;       /* Save name in work    */

            while( c != '\n' && c != EOF_CHAR )
                {
                if( (ret = save( global, c )) )
                    return(ret);

                c = get( global );
                }

            unget( global );

            if( (ret = save( global, EOS )) )
                return(ret);

            /*
             * Split #line argument into <line-number> and <name>
             * We subtract 1 as we want the number of the next line.
             */
            global->line = atoi(global->work) - 1;     /* Reset line number    */

            for( tp = global->work; isdigit(*tp) || type[(unsigned)*tp] == SPA; tp++)
                ;             /* Skip over digits */

            if( *tp != EOS )
                {
                /* Got a filename, so:  */

                if( *tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL )
                    {
                    tp++;           /* Skip over left quote */

                    *ep = EOS;      /* And ignore right one */
                    }

                if( global->infile->progname != NULL )
                    /* Give up the old name if it's allocated.   */
                    free( global->infile->progname );

                global->infile->progname = savestring( global, tp );
                }

            global->wrongline = TRUE;           /* Force output later   */
            break;

        case L_include:
            ret = doinclude( global );
            if( ret )
                return(ret);
            break;

        case L_define:
            ret = dodefine( global );
            if( ret )
                return(ret);
            break;

        case L_undef:
            doundef( global );
            break;

        case L_else:
            if( global->ifptr == &global->ifstack[0] )
                {
                cerror( global, ERROR_STRING_MUST_BE_IF, global->tokenbuf );

                dump_line( global, counter );

                return( FPP_OK );
                }
            else if( (*global->ifptr & ELSE_SEEN) != 0 )
                {
                cerror( global, ERROR_STRING_MAY_NOT_FOLLOW_ELSE, global->tokenbuf );

                dump_line( global, counter );

                return( FPP_OK );
                }

            *global->ifptr |= ELSE_SEEN;

            if( (*global->ifptr & WAS_COMPILING) != 0 )
                {
                if( compiling || (*global->ifptr & TRUE_SEEN) != 0 )
                    compiling = FALSE;
                else
                    {
                    compiling = TRUE;
                    }
                }
            break;

        case L_elif:
            if( global->ifptr == &global->ifstack[0] )
                {
                cerror( global, ERROR_STRING_MUST_BE_IF, global->tokenbuf );

                dump_line( global, counter );

                return( FPP_OK );
                }
            else if( (*global->ifptr & ELSE_SEEN) != 0 )
                {
                cerror( global, ERROR_STRING_MAY_NOT_FOLLOW_ELSE, global->tokenbuf );

                dump_line( global, counter );

                return( FPP_OK );
                }

            if( (*global->ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING )
                {
                compiling = FALSE;        /* Done compiling stuff */

                dump_line( global, counter );   /* Skip this clause */

                return( FPP_OK );
                }

            ret = doif( global, L_if );

            if( ret )
                return(ret);

            break;

        case L_error:
            cerror(global, ERROR_ERROR);
            break;

        case L_if:
        case L_ifdef:
        case L_ifndef:
            if( ++global->ifptr < &global->ifstack[BLK_NEST] )
                {
                *global->ifptr = WAS_COMPILING;

                ret = doif( global, hash );

                if( ret )
                    return(ret);

                break;
                }

            cfatal( global, FATAL_TOO_MANY_NESTINGS, global->tokenbuf );

            return( FPP_TOO_MANY_NESTED_STATEMENTS );

        case L_endif:
            if( global->ifptr == &global->ifstack[0] )
                {
                cerror( global, ERROR_STRING_MUST_BE_IF, global->tokenbuf );

                dump_line( global, counter );

                return(FPP_OK);
                }

            if( !compiling && (*global->ifptr & WAS_COMPILING) != 0 )
                global->wrongline = TRUE;

            compiling = ((*global->ifptr & WAS_COMPILING) != 0);

            --global->ifptr;

            break;

        case L_assert:
            {
            int result;

            ret = eval( global, &result );

            if(ret)
                return(ret);

            if( result == 0 )
                cerror( global, ERROR_PREPROC_FAILURE );
            }
            break;

        case L_pragma:
            /*
             * #pragma is provided to pass "options" to later
             * passes of the compiler.  cpp doesn't have any yet.
             */
            Putstring( global, "#pragma " );

            while( (c = get( global ) ) != '\n' && c != EOF_CHAR )
                Putchar( global, c );

            unget( global );

            Putchar( global, '\n' );

            break;

        default:
            /*
             * Undefined #control keyword.
             * Note: the correct behavior may be to warn and
             * pass the line to a subsequent compiler pass.
             * This would allow #asm or similar extensions.
             */
            if( global->warnillegalcpp )
                cwarn( global, WARN_ILLEGAL_COMMAND, global->tokenbuf );

            Putchar( global, '#' );
            Putstring( global, global->tokenbuf );
            Putchar( global, ' ' );

            while( (c = get( global ) ) != '\n' && c != EOF_CHAR )
                Putchar( global, c );

            unget( global );

            Putchar( global, '\n' );

            break;
        }

    if( hash != L_include )
        {
        #if OLD_PREPROCESSOR
        /*
         * Ignore the rest of the #control line so you can write
         *      #if foo
         *      #endif  foo
         */
        dump_line( global, counter );         /* Take common exit */

        return( FPP_OK );
        #else
          if (skipws(global) != '\n')
            {
            cwarn( global, WARN_UNEXPECTED_TEXT_IGNORED );

            skipnl( global );
            }
        #endif
        }

    (*counter)++;

    return( FPP_OK );
}
Exemple #17
0
INLINE FILE_LOCAL
ReturnCode doinclude( struct Global *global )
{
    /*
     *  Process the #include control line.
     *  There are three variations:
     *
     *      #include "file" search somewhere relative to the
     *                      current source file, if not found,
     *                      treat as #include <file>.
     *
     *      #include <file> Search in an implementation-dependent
     *                      list of places.
     *
     *      #include token  Expand the token, it must be one of
     *                      "file" or <file>, process as such.
     *
     *  Note:   the November 12 draft forbids '>' in the #include <file> format.
     *          This restriction is unnecessary and not implemented.
     */

    int c;
    int delim;
    ReturnCode ret;

    delim = skipws( global );

    if( (ret = macroid( global, &delim )) )
        return(ret);

    if( delim != '<' && delim != '"' )
        {
        cerror( global, ERROR_INCLUDE_SYNTAX );

        return( FPP_OK );
        }

    if( delim == '<' )
        delim = '>';

    global->workp = global->work;

    while( (c = get(global)) != '\n' && c != EOF_CHAR )
        if( (ret = save( global, c )) )       /* Put it away.                */
            return( ret );

    unget( global );                        /* Force nl after include      */

    /*
     * The draft is unclear if the following should be done.
     */
    while( --global->workp >= global->work &&
        (*global->workp == ' ' || *global->workp == '\t' || *global->workp == '\r') )
        ;               /* Trim blanks from filename    */

    if( *global->workp != delim )
        {
        cerror( global, ERROR_INCLUDE_SYNTAX );

        return(FPP_OK);
        }

    *global->workp = EOS;         /* Terminate filename       */

    ret = openinclude( global, global->work, (delim == '"') );

    if( ret && global->warnnoinclude )
        {
        /*
         * Warn if #include file isn't there.
         */
        cwarn( global, WARN_CANNOT_OPEN_INCLUDE, global->work );
        }

    return( FPP_OK );
}
Exemple #18
0
const char *    set_encoding(
    char *  name,       /* Name of encoding specified   */
    char *  env,        /* Name of environment variable */
    int     pragma
        /* 2: #pragma setlocale, 1: #pragma __setlocale, 0: not #pragma */
)
/*
 * Search the encoding specified and re-initialize mbchar settings.
 */
{
    const char *    unknown_encoding
            = "Unknown encoding: %s%.0ld%.0s";          /* _W1_ */
    const char *    too_long
            = "Too long encoding name: %s%.0ld%.0s";    /* _E_  */
    const char *    loc = "";
    int     alias;
    char    norm[ NAMLEN];
            /*
             * Normalized name (removed 'xxxxx.', stripped '_', '-', '.'
             * and lowered.
             */

    if (strlen( name) >= NAMLEN) {
        if ((env || pragma) && (warn_level & 1)) {
            cwarn( too_long, name, 0L, NULL);
        } else {
            mcpp_fprintf( ERR, too_long, name);
            mcpp_fputc( '\n', ERR);
        }
    }
    strcpy( norm, name);
    if (norm[ 5] == '.')
        memmove( norm, norm + 5, strlen( norm + 5) + 1);
        /* Remove initial 'xxxxx.' as 'ja_JP.', 'en_US.' or any other   */
    conv_case( norm, norm + strlen( norm), LOWER);
    strip_bar( norm);

    if (strlen( name) == 0) {                       /* ""       */
        mbchar = MBCHAR;    /* Restore to the default encoding  */
    } else if (memcmp( norm, "iso8859", 7) == 0     /* iso8859* */
            || memcmp( norm, "latin", 5) == 0       /* latin*   */
            || memcmp( norm, "en", 2) == 0) {       /* en*      */
        mbchar = 0;                 /* No multi-byte character  */
    } else {
        alias = 2;
#if COMPILER == MSC
        if (pragma == SETLOCALE)        /* #pragma setlocale    */
            alias = 0;
#endif
        loc = search_encoding( norm, alias);        /* Search the name  */
    }
    if (loc == NULL) {
        if ((env || pragma) && (warn_level & 1)) {
            cwarn( unknown_encoding, name, 0L, NULL);
        } else {                        /* -m option            */
            mcpp_fprintf( ERR, unknown_encoding, name);
            mcpp_fputc( '\n', ERR);
        }
    } else {
        mb_init();                      /* Re-initialize        */
    }
    return  loc;
}