⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cl.cpp

📁 STLstlfilt.zip
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
 * cl.cpp: "Proxy CL" STL Error Filter Driver for VC++6/7
 *
 * Framework by Leor Zolman
 *				BD Software
 *				(leor@bdsoft.com)
 *
 * Win32 piping logic by Thomas Becker
 *
 * (C) Copyright Leor Zolman 2002. Permission to copy, use, modify, sell and
 * distribute this software is granted provided this copyright notice appears
 * in all copies. This software is provided "as is" without express or implied
 * warranty, and with no claim as to its suitability for any purpose.
 */

#define CL_ID		"BD Software Proxy CL v2.43a"

/* Release 2.43a - 1/15/2004
 *
 * Calls native CL (renamed to CL2.EXE) to perform compilation; for
 * files with applicable extensions, filters output through a Perl
 * script to simplify cryptic STL messages
 *
 * Options: /silent         Disables STL filtering status message and auto-
 *       or -silent         matically adds /nologo option to NATIVE_CL command line
 *
 *			/nf				"No Filtering" - behaves as if filtering were disabled
 *			/iter:x			Sets iterator policy to x (S, M or L)
 *			/alloc:x		Sets allocator policy to x (S or L) [for .NET only]
 *          /func:x			Sets "common functor" policy to x (S or L) [for .NET only]
 *			/with:x			Set "with" clause policy
 *          /width:xx		Sets column to wrap output lines. 0=no wrap (the default).
 *          /break:x		Line break algorithm (D or P)
 *          /cbreak:x		Comma break policy (B or A)
 *          /closewrap:x	Wrap before unmatched close delims (Y or N)
 *          /meta:x			Choose metaprogramming pre-config (Y or N)
 *          /lognative      Create debugging log file NativeLog.txt in current dir
 *
 * If the file designated by the CONFIG_FILE symbol (PROXY-CL.INI as
 * distributed) is present in the Windows directory upon startup, CL reads
 * configuration information from the file to override like-named defaults
 * as #defined later in this source file. The allowed configuration options,
 * in their respective sections (with default settings shown) are:
 *
 *      [common]
 *		FILTER_SCRIPT=c:\STLFilt.pl
 *		TOGGLE_FILE_DIR=c:\
 *		NATIVE_CL=cl2
 *		PERL_EXE=c:\perl\bin\perl
 *		
 *      [proxy.cl]
 *      SILENT=false
 *		DEBUG=false
 *		DEBUG_DIR=c:\
 *		OUTPUT_WIDTH=0
 *		ITERATOR_POLICY=M
 *		ALLOCATOR_POLICY=S
 *      FUNCTOR_POLICY=S
 *      WITH_POLICY=S
 *      LOG_NATIVE_MSGS=N
 *		BREAK=P
 *		CBREAK=B
 *		CLOSEWRAP=Y
 *
 * For more details on the Proxy-CL.INI options, see the sample Proxy-CL.INI file.
 * For general information, see README.txt.
 * The Quick Start guide is QUICKSTART.txt.
 *
 * Error filtering is toggled by the presence (or absence) of
 * the file FILTERING.ON in the TOGGLE_FILE_DIR directory.
 * Toggling the existence of this file is managed either by the STLFilt.BAT
 * batch file or the STLTask.EXE taskbar icon app.
 *
 * Compile: cl /Ox /GX cl.cpp setargv.obj
 *
 * Note: Be careful not to compile this cl.cpp file using any version
 *       of CL.EXE resident in the current directory, or the linker won't
 *		 be able to overwrite it to create the new CL.EXE...
 *****************************************************************************/

#include <iostream>
#include <fstream>
#include <string>
#include <process.h>				// for _spawnvp()
#include <windows.h>				// needed to create processes
#include <sys/stat.h>

////////////////////////////////////////////////////////////////////////////////////////////
//
// User-configurable settings: The next four #defines specify default settings for each
// of the given options. They may be overriden by settings in the configuation file.
//
// Note: Regardless of whether or not any of the pathnames defined below contain embedded
//		 spaces, NEVER use "extra" quotes (as required in older versions of CL.CPP)
//
//		 Remember to use double-backslashes (\\) for directory delimiters in pathnames!
//

#define PERL_EXE		"c:\\perl\\bin\\perl"		// Your Perl interpreter
#define FILTER_SCRIPT	"c:\\STLFilt.pl"			// Perl script pathname

#define TOGGLE_FILE_DIR	"c:\\"						// filtering toggle file directory
													//	(see companion variable FILT_BASE
													//   in STLFILT.BAT)
#define	FILT_FILE		"filtering.on"				// Toggle file in "enabled" state

#define NATIVE_CL		"cl2"						// name of standard CL.EXE, must
													//		reside in a system PATH dir

#define CONFIG_FILE		"PROXY-CL.INI"				// if full path not specified, default
													// is Windows directory

#define SILENT			false						// true to surpress sign-on message (when
													//	filtering C++ source files)

#define DEBUG			false						// if true, logging enabled by default
#define DEBUG_CAPABLE	1							// 1 to compile with debugging features
#define DEBUG_DIR		"C:\\"						// default directory to log debug info to
#define DEBUG_LOGFILE	"cl-dblog.txt"				// main debugging log file
#define DEBUG_ATFILE	"atfile.txt"				// project @file copied to this file
#define LOG_NATIVE_MSGS false						// if true, log native message by default
#define OUTPUT_WIDTH	"0"							// default column to wrap output at (0: no wrap)
#define ITERATOR_POLICY	"M"							// default iterator policy
#define	ALLOCATOR_POLICY "S"						// default allocator policy (.NET only)
#define FUNCTOR_POLICY	"S"							// default functor policy (.NET only)
#define WITH_POLICY		"S"

#define BREAK			"P"							// default break algorithm
#define CBREAK			"A"							// default comma break policy
#define CLOSEWRAP		"N"							// default closewrap policy

const std::string filterExt[] =						// Filter only output from compiling
{													// files with these extensions
	".cpp",
	".cxx",
	".cc"
};

const std::string objExt[] =						// If we see these extensions on any
{													// CL arguments at the end of the line,
	".lib",											// keep searching for some other
	".obj",											// extension to qualify for filtering...
	".o"
};

const std::string exeExt[] =						// for checking for .EXE extensions
{													// in configuration pathnames
	".exe"
};

// END User-configurable settings
////////////////////////////////////////////////////////////////////////////////////////////

const size_t nfilter = sizeof(filterExt) / sizeof(std::string);
const size_t nobj = sizeof(objExt) / sizeof(std::string);

BOOL WriteEofToPipe(HANDLE hPipe);
bool hasExt(const std::string &filename, const std::string extensions[], int);
int doWin32Stuff(char *full_filt_cmd, char *cmdline);
void chompSpace(std::string &pathname);				// remove trailing whitespace, if any
void chompSlash(std::string &pathname);				// remove trailing slash, if any
void stripComment(std::string &txt);				// remove trailing comment, if any
void stripQuotes(std::string &txt, const std::string &unprocessed_line);   // strip quotation marks
void massage_pathname(std::string &txt);			// give path/file names the full treatment:


#if DEBUG_CAPABLE
void logit(const std::string &msg);
std::string toString(int n);
#define log(s) logit(s)
#else
#define log(s)
#endif

std::string native_cl;
std::string debug_dir;
std::string debug_log;
std::string configFile = CONFIG_FILE;

bool debug;

int main(int argc, char *argv[])
{
	using namespace std;
	const int MAXLINE = 200;						// max length of config file line
	char linebuf[MAXLINE] = "";
	FILE *fp;
	bool filtering = false;							// not filtering by default
	bool silent = false;							// not silent by default
	bool log_native_msgs;
	string full_filt_cmd;
	string filename;								// file to compile
	string perl_exe;
	string filter_script;
	string toggle_file;
	string toggle_file_dir;
	int output_width;
	string iterator_policy;
	string allocator_policy;
	string functor_policy;
	string with_policy;
	string break_algorithm;
	string cbreak;
	string closewrap;
	bool use_meta = false;
	string meta;
	
	int i;
	
	if (argc == 1)
	{
		cerr << CL_ID << endl;
		cerr << "usage: cl [ /lognative /silent /nf /iter:x /alloc:x /func:x /width:nn \n"
				"            /break:x /cbreak:x /closewrap;x /meta[:x] ] [MSVC opts] file(s)" << endl;
		exit(1);
	}
	
	GetPrivateProfileString( "proxy.cl", "debug_dir", DEBUG_DIR,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	debug_dir = linebuf;
	massage_pathname(debug_dir);
	
	GetPrivateProfileString( "proxy.cl", "debug", DEBUG ? "true" : "false",
							 linebuf, sizeof(linebuf), configFile.c_str() );
	char c;
	debug = (c = tolower(linebuf[0])) == 't' || c == 'y' || c == '1';

	if (debug)
#if DEBUG_CAPABLE
	{
		debug_log = debug_dir + "\\" + DEBUG_LOGFILE;
		log("-------------------------------------------------------------------");
		log(string("debug = ") + (debug ? "true" : "false"));
		log("debug_log = " + debug_log);
	}
#else
		cerr << "Proxy CL: WARNING: debug option specified, but Proxy CL not debug capable!" << endl;
#endif
		
	log("configFile is: " + configFile);

	GetPrivateProfileString( "proxy.cl", "log_native_msgs",
							 LOG_NATIVE_MSGS ? "true" : "false",
							 linebuf, sizeof(linebuf), configFile.c_str() );
	log_native_msgs = (c = tolower(linebuf[0])) == 't' || c == 'y' || c == '1';
	log(string("log_native_msgs = ") + (log_native_msgs ? "true" : "false"));
	

	GetPrivateProfileString( "common", "perl_exe", PERL_EXE,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	perl_exe = linebuf;
	massage_pathname(perl_exe);
	if (!hasExt(perl_exe, exeExt, 1))			// make sure we have an .EXE extension
		perl_exe += ".exe";
	
	log("perl_exe = '" + perl_exe + "'");

	GetPrivateProfileString( "common", "filter_script", FILTER_SCRIPT,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	filter_script = linebuf;
	massage_pathname(filter_script);
	log("filter_script = '" + filter_script + "'");

	GetPrivateProfileString( "common", "toggle_file_dir", TOGGLE_FILE_DIR,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	toggle_file_dir = linebuf;
	massage_pathname(toggle_file_dir);
	log("toggle_file_dir = '" + toggle_file_dir + "'");

	GetPrivateProfileString( "common", "native_cl", NATIVE_CL,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	native_cl = linebuf;
	massage_pathname(native_cl);
	log("native_cl = '" + native_cl + "'");

	GetPrivateProfileString( "proxy.cl", "iterator_policy", ITERATOR_POLICY,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	iterator_policy = linebuf;
	stripComment(iterator_policy);
	log("iterator_policy = " + iterator_policy);

	GetPrivateProfileString( "proxy.cl", "allocator_policy", ALLOCATOR_POLICY,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	allocator_policy = linebuf;
	stripComment(allocator_policy);
	log("allocator_policy = " + allocator_policy);

	GetPrivateProfileString( "proxy.cl", "functor_policy", FUNCTOR_POLICY,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	functor_policy = linebuf;
	stripComment(functor_policy);
	log("functor_policy = " + functor_policy);


	GetPrivateProfileString( "proxy.cl", "with_policy", WITH_POLICY,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	with_policy = linebuf;
	stripComment(with_policy);
	log("with_policy = " + with_policy);

	GetPrivateProfileString( "proxy.cl", "break", BREAK,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	break_algorithm = linebuf;
	stripComment(break_algorithm);
	log("break algorithm = " + break_algorithm);

	GetPrivateProfileString( "proxy.cl", "cbreak", CBREAK,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	cbreak = linebuf;
	stripComment(cbreak);
	log("cbreak policy = " + cbreak);

	GetPrivateProfileString( "proxy.cl", "closewrap", CLOSEWRAP,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	closewrap = linebuf;
	stripComment(functor_policy);
	log("functor_policy = " + functor_policy);

	GetPrivateProfileString( "proxy.cl", "silent", SILENT ? "true" : "false",
							 linebuf, sizeof(linebuf), configFile.c_str() );
	silent = (c = tolower(linebuf[0])) == 't' || c == 'y' || c == '1';
	log(string("silent = ") + (silent ? "true" : "false"));

	GetPrivateProfileString( "proxy.cl", "output_width", OUTPUT_WIDTH,
							 linebuf, sizeof(linebuf), configFile.c_str() );
	output_width = atoi(linebuf);
	log("output_width = " + output_width);

	full_filt_cmd = "\"" + perl_exe + "\" \"" + filter_script + "\"";
	log("full_filt_cmd = '" + full_filt_cmd + "'");

	toggle_file = toggle_file_dir + "\\" + FILT_FILE;
	log("toggle_file = '" + toggle_file + "'");

#if DEBUG_CAPABLE
	for (i = 1; i < argc; i++)
		log("Arg #" + toString(i) + " is '" + argv[i] + "'");
#endif
	
	log("-----------");

	if (argv[1][0] == '@')							// indirect command line?
	{
		log(string("Indirect command line detected:") + argv[1] + "\nContents:");

#if DEBUG_CAPABLE			// replicate the @file produced by VC, since it is deleted immediately:
		if (debug)
			system((string("copy ") + &argv[1][1] + " " + debug_dir +
											"\\" + DEBUG_ATFILE).c_str());
#endif

		ifstream fin(&argv[1][1]);
		if (!fin)
		{
			string msg = string("Proxy CL: Bad @ filename? First Command line arg:") +
							 argv[1];
			log(msg);
			cerr << msg << endl;
			exit(1);
		}

		string linebuf, lastline;
		while (getline(fin, linebuf))
		{
			lastline = linebuf;
			log(linebuf);
		}
		fin.close();

		log("The complete final line from the indirect file:\n" + lastline);

		bool seenquote = false;
		for (i = lastline.length() - 1; i >= 0; i--)
			if (lastline[i] == '"')
				if (!seenquote)
				{
					seenquote = true;
					lastline.resize(i);
				}
				else
					break;
			else if (lastline[i] == ' ' && !seenquote)
				break;
		
		filename = lastline.substr(i + 1);
		log("filename detected indirectly: '" + filename + "'");
	}
	else
		for (i = argc - 1; i > 0; i--)
		{
			if (hasExt(argv[i], objExt, nobj ))		// ignore libraries, obj files
				continue;
			if (strchr(argv[i], '.') == NULL)		// ignore options (no extensions)
				continue;
			filename = argv[i];						// first non-lib/obj/option is the filename
			break;
		}
	
	if (filename.length() == 0 || !hasExt(filename, filterExt, nfilter )) // if extension of filename is not in the
		silent = true;								// approved list, never filter it
	else
	{
		log("about to open toggle_file '"+toggle_file+"'");
		if((fp = fopen(toggle_file.c_str(), "r")) != NULL)
		{												// otherwise, filter iff
			filtering = true;							// toggle_file exists
			fclose(fp);
		}
	}
	
	string args = " ";								// replicate CL command line args

	char **new_argv = new char *[argc + 1];			// also create a new "argv" with each arg in
	size_t new_argc = 0;							// quotes in case we're not filtering and
													// have to use _spawnvp()
	for (i = 0; i < argc; i++)
	{
		if (!stricmp(argv[i],"/silent") || !stricmp(argv[i],"-silent"))
		{
			string nologo = "/nologo";
			silent = true;
			args += nologo;
			new_argv[new_argc] = new char[nologo.length()];
			strcpy(new_argv[new_argc++], nologo.c_str());
		}
		else if (!stricmp(argv[i],"/nf") || !stricmp(argv[i],"-nf"))
		{
			filtering = false;
			silent = true;
		}
		else if (!strnicmp(argv[i], "/iter:", 6)  || !strnicmp(argv[i], "-iter:", 6))
		{
			iterator_policy = &argv[i][6];
		}
		else if (!strnicmp(argv[i], "/alloc:", 7)  || !strnicmp(argv[i], "-alloc:", 7))
		{
			allocator_policy = &argv[i][7];
		}
		else if (!strnicmp(argv[i], "/func:", 6)  || !strnicmp(argv[i], "-func:", 6))
		{
			functor_policy = &argv[i][6];
		}
		else if (!strnicmp(argv[i], "/with:", 5)  || !strnicmp(argv[i], "-with:", 5))
		{
			with_policy = &argv[i][6];
		}
		else if (!strnicmp(argv[i], "/break:", 7)  || !strnicmp(argv[i], "-break:", 7))
		{
			break_algorithm = &argv[i][7];
		}
		else if (!strnicmp(argv[i], "/cbreak:", 8)  || !strnicmp(argv[i], "-cbreak:", 8))
		{
			cbreak = &argv[i][8];
		}
		else if (!strnicmp(argv[i], "/closewrap:", 11)  || !strnicmp(argv[i], "-closewrap:", 11))
		{
			closewrap = &argv[i][11];
		}
		else if (!strnicmp(argv[i], "/meta:", 6)  || !strnicmp(argv[i], "-meta:", 6))
		{
			meta = &argv[i][6];
			use_meta = true;
		}
		else if (!strnicmp(argv[i], "/meta", 5) || !strnicmp(argv[i], "-meta", 5))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -