Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

287 lines
8.0 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. ppcmd.cxx
  5. Abstract:
  6. This file preprocesses the command line to check for response file
  7. input.
  8. Notes:
  9. This file extends the register args routine from the command analyser to
  10. incorporate the response files.
  11. Author:
  12. vibhasc 03-16-91 Created to conform to coding guidelines.
  13. NishadM 02-03-97 rewrite to simplify, allow DBCS, remove bugs
  14. ----------------------------------------------------------------------------*/
  15. #if 0
  16. Notes
  17. -----
  18. We want to make implementations of the response file completely transparent
  19. to the rest of the compiler. The response file is specified to midl using
  20. the syntax:
  21. midl <some switches> @full response file path name <more switches>.
  22. We dont want to restrict the user from specifyin the response file at any
  23. place in the command line, any number of times. At the same time we do not
  24. want the command analyser to even bother about the response file, to keep
  25. implementation very localised. In order to do that, we do a preprocessing
  26. on the command line to look for the response file command.
  27. The command analyser expects the arguments in an argv like array. The
  28. preprocessor will creates this array, expanding all response file commands
  29. into this array, so that the command analyser does not even notice the
  30. difference.
  31. We use our fancy dynamic array implementation to create this argv-like
  32. array.
  33. Things to keep in mind:
  34. 1. The response file needs to be parsed.
  35. 2. Each option must be completely specified in a command line. i.e
  36. the option cannot be continued in a separate line using the continuation
  37. character or anything.
  38. 3. Each switch must be presented just the same way that the os command
  39. processor does. We need to analyse the string for escaped '"'
  40. #endif // 0
  41. #pragma warning ( disable : 4514 )
  42. /*****************************************************************************
  43. local defines and includes
  44. *****************************************************************************/
  45. #include "nulldefs.h"
  46. extern "C" {
  47. #include <stdio.h>
  48. #include <string.h>
  49. #include <ctype.h>
  50. }
  51. #include "common.hxx"
  52. #include "errors.hxx"
  53. #include "idict.hxx"
  54. extern BOOL fNoLogo;
  55. extern void RpcError( char *, short, STATUS_T, char *);
  56. bool
  57. AnalyseResponseFile (
  58. char* p,
  59. IDICT* pIDict
  60. );
  61. char *
  62. ParseResponseFile (
  63. FILE* h,
  64. unsigned int uLineNumber,
  65. char* szFilename
  66. );
  67. /*****************************************************************************/
  68. bool
  69. PPCmdEngine(
  70. int argc,
  71. char * argv[],
  72. IDICT * pIDict )
  73. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  74. Routine Description:
  75. command preprocessor engine.
  76. Arguments:
  77. argc - count of the number of arguments
  78. argv - vector of arguments to the program
  79. pIDict - dictionary of arguments to be returned.
  80. Return Value:
  81. Pointer to an indexed dictionary (actually a dynamic array ), containing
  82. the entire set of arguments, including the ones from the response file.
  83. Notes:
  84. Go thru each of the arguments. If you find a response file switch, pick up
  85. the arguments from the response file and add to the argument list.
  86. ----------------------------------------------------------------------------*/
  87. {
  88. int iArg;
  89. char * p,
  90. * q;
  91. bool fNoLogo = false;
  92. for( iArg = 0; iArg < argc ; ++iArg )
  93. {
  94. p = argv[ iArg ];
  95. switch( *p )
  96. {
  97. case '@':
  98. fNoLogo |= AnalyseResponseFile( p, pIDict );
  99. break;
  100. case '/':
  101. case '-':
  102. // detect /nologo early in the cmd parse
  103. if ( !strcmp( p+1, "nologo" ) )
  104. fNoLogo = true;
  105. // fall through
  106. default:
  107. q = new char[ strlen( p ) + 1 ];
  108. strcpy( q, p );
  109. pIDict->AddElement( (IDICTELEMENT) q );
  110. break;
  111. }
  112. }
  113. return !fNoLogo;
  114. }
  115. bool
  116. AnalyseResponseFile (
  117. char* p,
  118. IDICT* pIDict
  119. )
  120. {
  121. FILE* pResponseFile;
  122. bool fNoLogo = false;
  123. // try to open the response file.
  124. // ++p to skip '@' preceding the filename.
  125. if ( ( pResponseFile = fopen( ++p, "r") ) == (FILE *)NULL )
  126. {
  127. RpcError( (char *)0, 1, CANNOT_OPEN_RESP_FILE, p );
  128. }
  129. else
  130. {
  131. char* szArg = 0;
  132. unsigned int uLineNumber = 1;
  133. // the response file successfully opened. parse it.
  134. while ( ( szArg = ParseResponseFile(
  135. pResponseFile,
  136. uLineNumber,
  137. p
  138. ) ) != 0 )
  139. {
  140. if ( 0 == strcmp(szArg, "-nologo")
  141. || 0 == strcmp(szArg, "/nologo") )
  142. {
  143. fNoLogo = true;
  144. }
  145. pIDict->AddElement( szArg );
  146. }
  147. fclose( pResponseFile );
  148. }
  149. return fNoLogo;
  150. }
  151. char *
  152. ParseResponseFile (
  153. FILE* h,
  154. unsigned int uLineNumber,
  155. char* szFilename
  156. )
  157. {
  158. char szTempArg[1024];
  159. char* p = szTempArg;
  160. int ch = 0;
  161. // initialize pTempArg
  162. *p = 0;
  163. // remove all the leading spaces
  164. do
  165. {
  166. ch = fgetc( h );
  167. if ( ch == '\n' )
  168. {
  169. uLineNumber++;
  170. }
  171. }
  172. while ( isspace( ch ) );
  173. if ( ch == '"' )
  174. {
  175. // if the argument is within quotes,
  176. // all chars including spaces make up the
  177. // argument. The quote is treated as a delimiter
  178. do
  179. {
  180. ch = fgetc( h );
  181. *p++ = (char) ch;
  182. if ( ch == '\\' )
  183. {
  184. // double back slash is interpreted as one.
  185. ch = fgetc( h );
  186. *p++ = (char) ch;
  187. if ( ch == '\\' )
  188. {
  189. p--;
  190. }
  191. }
  192. else if ( ch == '\n' )
  193. {
  194. uLineNumber++;
  195. }
  196. }
  197. while ( ch != '"' && ch != EOF );
  198. *(p - 1) = 0;
  199. }
  200. else if ( ch == '@' )
  201. {
  202. // first char of the argument is a '@'
  203. // this means a response file with a response
  204. // file. Flag an error.
  205. RpcError( szFilename,
  206. (short)uLineNumber,
  207. NESTED_RESP_FILE,
  208. (char *)0 );
  209. }
  210. else if ( ch != EOF )
  211. {
  212. // if the argument is not with in quotes,
  213. // white spaces are delimiters.
  214. *p++ = (char)ch;
  215. do
  216. {
  217. ch = fgetc( h );
  218. *p++ = (char)ch;
  219. if ( ch == '\n' )
  220. {
  221. uLineNumber++;
  222. }
  223. }
  224. while ( !isspace( ch ) && ch != EOF );
  225. *(p - 1) = 0;
  226. }
  227. size_t nSize = strlen( szTempArg );
  228. char* szRet = 0;
  229. if ( nSize != 0 )
  230. {
  231. szRet = new char[nSize+1];
  232. if ( szRet != 0 )
  233. {
  234. strcpy( szRet, szTempArg );
  235. }
  236. }
  237. return szRet;
  238. }