ReactOS  r76032
parser.c File Reference
#include "precomp.h"
Include dependency graph for parser.c:

Go to the source code of this file.

Macros

#define C_OP_LOWEST   C_MULTI
 
#define C_OP_HIGHEST   C_PIPE
 
#define IF_MAX_UNARY   IF_EXIST
 
#define IF_MAX_COMPARISON   IF_NEQ
 
#define STANDARD_SEPS   _T(",;=")
 
#define CHAR(Char)
 
#define STRING(String)
 
#define PRINTF(Format,...)
 
#define RECURSE(Subcommand)
 

Enumerations

enum  {
  TOK_END, TOK_NORMAL, TOK_OPERATOR, TOK_REDIRECTION,
  TOK_BEGIN_BLOCK, TOK_END_BLOCK
}
 

Functions

static BOOL IsSeparator (TCHAR Char)
 
static TCHAR ParseChar ()
 
static void ParseError ()
 
static int ParseToken (TCHAR ExtraEnd, TCHAR *Separators)
 
static BOOL ParseRedirection (REDIRECTION **List)
 
static PARSED_COMMANDParseCommandOp (int OpType)
 
static PARSED_COMMANDParseBlock (REDIRECTION *RedirList)
 
static PARSED_COMMANDParseIf (void)
 
static PARSED_COMMANDParseFor (void)
 
static PARSED_COMMANDParseRem (void)
 
static DECLSPEC_NOINLINE
PARSED_COMMAND
ParseCommandPart (REDIRECTION *RedirList)
 
static PARSED_COMMANDParsePrimary (void)
 
PARSED_COMMANDParseCommand (LPTSTR Line)
 
VOID EchoCommand (PARSED_COMMAND *Cmd)
 
TCHARUnparse (PARSED_COMMAND *Cmd, TCHAR *Out, TCHAR *OutEnd)
 
VOID FreeCommand (PARSED_COMMAND *Cmd)
 

Variables

static const TCHAR OpString [][3] = { _T("&"), _T("||"), _T("&&"), _T("|") }
 
static const TCHAR RedirString [][3] = { _T("<"), _T(">"), _T(">>") }
 
static const TCHAR *const IfOperatorString []
 
static BOOL bParseError
 
static BOOL bLineContinuations
 
static TCHAR ParseLine [CMDLINE_LENGTH]
 
static TCHARParsePos
 
static TCHAR CurChar
 
static TCHAR CurrentToken [CMDLINE_LENGTH]
 
static int CurrentTokenType
 
static int InsideBlock
 

Macro Definition Documentation

#define C_OP_HIGHEST   C_PIPE

Definition at line 8 of file parser.c.

Referenced by ParseCommandOp().

#define C_OP_LOWEST   C_MULTI
#define CHAR (   Char)
Value:
{ \
if (Out == OutEnd) return NULL; \
*Out++ = Char; }
char Char
Definition: bzip2.c:161
smooth NULL
Definition: ftsmooth.c:557
return(0)
if(!(yy_init))
Definition: macro.lex.yy.c:704

Referenced by AddConsoleAliasA(), AtapiDmaReinit(), AtapiHwInitialize__(), AtapiStartIo__(), AtaSetTransferMode(), BytesInHostent(), BytesInProtoent(), BytesInServent(), calc_arg_size(), CmpCopyName(), CmpGetNameControlBlock(), co_UserCreateWindowEx(), ComputeStringSize(), ConDrvReadConsoleOutputString(), ConDrvWriteConsoleOutputString(), ConMgrSerialPortConsumer(), CopyCompStringIMEtoClient(), CopyHostentToBuffer(), CopyProtoentToBuffer(), CopyServentToBuffer(), CPin::CPin(), CSR_API(), DuplicateStringAEx(), CPin::EnumMediaTypes(), ExpLoadBootSymbols(), FAST486_OPCODE_HANDLER(), FlatBuf_Arg_WriteString(), FONT_TextMetricWToA(), FsRtlIsDbcsInExpression(), FsRtlNotifyFilterChangeDirectory(), FsRtlNotifyFilterReportChange(), gdb_receive_packet(), get_type_size(), GetServiceDisplayNameA(), GetServiceKeyNameA(), GspGetPacket(), HCR_GetClassNameA(), HEXEDIT_WM_CHAR(), IntWideCharToMultiByteCP(), IntWideCharToMultiByteSYMBOL(), IntWideCharToMultiByteUTF8(), IPADDRESS_SubclassProc(), KbdHid_InsertScanCodes(), KdbpSymUnicodeToAnsi(), KdInitSystem(), KeBugCheckUnicodeToAnsi(), KeInitializeProcess(), LdrpGetProcedureAddress(), ListBoxWndProc_common(), main(), MountMgrNextDriveLetterWorker(), NLS_EnumCalendarInfo(), PciGetDescriptionMessage(), QueryCygwinEA(), RawUszAsz(), RtlInitAnsiString(), RtlIntegerToChar(), RtlLargeIntegerToChar(), RWComputeCHS(), ScBuildAnsiArgsVector(), test_GetPrinterData(), test_GetPrinterDataEx(), test_GetPrivateProfileString(), test_profile_sections_names(), UniataFindBusMasterController(), Unparse(), UrlUnescapeA(), UTF8fromUNICODE(), write_unicode2cp_table(), wvnsprintfA(), and wvnsprintfW().

#define IF_MAX_COMPARISON   IF_NEQ

Referenced by ParseIf().

#define IF_MAX_UNARY   IF_EXIST

Referenced by ParseIf().

#define PRINTF (   Format,
  ... 
)
Value:
{ \
UINT Len = _sntprintf(Out, OutEnd - Out, Format, __VA_ARGS__); \
if (Len > (UINT)(OutEnd - Out)) return NULL; \
Out += Len; }
smooth NULL
Definition: ftsmooth.c:557
return(0)
if(!(yy_init))
Definition: macro.lex.yy.c:704
#define Len
Definition: deflate.h:82
#define _sntprintf
Definition: xmlstorage.h:201
unsigned int UINT
Definition: ndis.h:50
#define UINT
Definition: msvc.h:27

Referenced by Unparse().

#define RECURSE (   Subcommand)
Value:
{ \
Out = Unparse(Subcommand, Out, OutEnd); \
smooth NULL
Definition: ftsmooth.c:557
return(0)
if(!(yy_init))
Definition: macro.lex.yy.c:704
TCHAR * Unparse(PARSED_COMMAND *Cmd, TCHAR *Out, TCHAR *OutEnd)
Definition: parser.c:844

Referenced by Unparse().

#define STANDARD_SEPS   _T(",;=")
Value:
{ \
if (Out + _tcslen(String) > OutEnd) return NULL; \
CHAR16 * String
Definition: acefiex.h:201
LPTSTR _stpcpy(LPTSTR, LPCTSTR)
Definition: misc.c:445
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:557
return(0)
if(!(yy_init))
Definition: macro.lex.yy.c:704

Referenced by Unparse(), and while().

Enumeration Type Documentation

anonymous enum
Enumerator
TOK_END 
TOK_NORMAL 
TOK_OPERATOR 
TOK_REDIRECTION 
TOK_BEGIN_BLOCK 
TOK_END_BLOCK 

Definition at line 38 of file parser.c.

Function Documentation

VOID EchoCommand ( PARSED_COMMAND Cmd)

Definition at line 752 of file parser.c.

Referenced by Batch(), and RunInstance().

753 {
754  TCHAR Buf[CMDLINE_LENGTH];
755  PARSED_COMMAND *Sub;
756  REDIRECTION *Redir;
757 
758  switch (Cmd->Type)
759  {
760  case C_COMMAND:
761  if (SubstituteForVars(Cmd->Command.First, Buf))
762  ConOutPrintf(_T("%s"), Buf);
763  if (SubstituteForVars(Cmd->Command.Rest, Buf))
764  ConOutPrintf(_T("%s"), Buf);
765  break;
766  case C_QUIET:
767  return;
768  case C_BLOCK:
769  ConOutChar(_T('('));
770  Sub = Cmd->Subcommands;
771  if (Sub && !Sub->Next)
772  {
773  /* Single-command block: display all on one line */
774  EchoCommand(Sub);
775  }
776  else if (Sub)
777  {
778  /* Multi-command block: display parenthesis on separate lines */
779  ConOutChar(_T('\n'));
780  do
781  {
782  EchoCommand(Sub);
783  ConOutChar(_T('\n'));
784  Sub = Sub->Next;
785  } while (Sub);
786  }
787  ConOutChar(_T(')'));
788  break;
789  case C_MULTI:
790  case C_IFFAILURE:
791  case C_IFSUCCESS:
792  case C_PIPE:
793  Sub = Cmd->Subcommands;
794  EchoCommand(Sub);
795  ConOutPrintf(_T(" %s "), OpString[Cmd->Type - C_OP_LOWEST]);
796  EchoCommand(Sub->Next);
797  break;
798  case C_IF:
799  ConOutPrintf(_T("if"));
800  if (Cmd->If.Flags & IFFLAG_IGNORECASE)
801  ConOutPrintf(_T(" /I"));
802  if (Cmd->If.Flags & IFFLAG_NEGATE)
803  ConOutPrintf(_T(" not"));
804  if (Cmd->If.LeftArg && SubstituteForVars(Cmd->If.LeftArg, Buf))
805  ConOutPrintf(_T(" %s"), Buf);
806  ConOutPrintf(_T(" %s"), IfOperatorString[Cmd->If.Operator]);
807  if (SubstituteForVars(Cmd->If.RightArg, Buf))
808  ConOutPrintf(_T(" %s "), Buf);
809  Sub = Cmd->Subcommands;
810  EchoCommand(Sub);
811  if (Sub->Next)
812  {
813  ConOutPrintf(_T(" else "));
814  EchoCommand(Sub->Next);
815  }
816  break;
817  case C_FOR:
818  ConOutPrintf(_T("for"));
819  if (Cmd->For.Switches & FOR_DIRS) ConOutPrintf(_T(" /D"));
820  if (Cmd->For.Switches & FOR_F) ConOutPrintf(_T(" /F"));
821  if (Cmd->For.Switches & FOR_LOOP) ConOutPrintf(_T(" /L"));
822  if (Cmd->For.Switches & FOR_RECURSIVE) ConOutPrintf(_T(" /R"));
823  if (Cmd->For.Params)
824  ConOutPrintf(_T(" %s"), Cmd->For.Params);
825  ConOutPrintf(_T(" %%%c in (%s) do "), Cmd->For.Variable, Cmd->For.List);
826  EchoCommand(Cmd->Subcommands);
827  break;
828  }
829 
830  for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
831  {
832  if (SubstituteForVars(Redir->Filename, Buf))
833  ConOutPrintf(_T(" %c%s%s"), _T('0') + Redir->Number,
834  RedirString[Redir->Mode], Buf);
835  }
836 }
#define FOR_DIRS
Definition: cmd.h:200
Definition: cmd.h:298
struct _PARSED_COMMAND * Subcommands
Definition: cmd.h:301
#define IFFLAG_IGNORECASE
Definition: cmd.h:227
VOID ConOutChar(TCHAR c)
Definition: console.c:123
BYTE Type
Definition: cmd.h:304
#define CMDLINE_LENGTH
Definition: help.h:12
struct _PARSED_COMMAND::@51::@53 Command
struct _PARSED_COMMAND::@51::@55 For
#define ConOutPrintf(szStr,...)
Definition: console.h:42
struct _PARSED_COMMAND::@51::@54 If
#define FOR_F
Definition: cmd.h:201
struct _PARSED_COMMAND * Next
Definition: cmd.h:302
#define C_OP_LOWEST
Definition: parser.c:7
REDIR_MODE Mode
Definition: cmd.h:357
#define _T(x)
Definition: tchar.h:1542
#define FOR_LOOP
Definition: cmd.h:202
Definition: cmd.h:298
Definition: cmd.h:298
BYTE Number
Definition: cmd.h:356
char TCHAR
Definition: xmlstorage.h:189
#define IFFLAG_NEGATE
Definition: cmd.h:226
TCHAR Filename[]
Definition: cmd.h:358
static const TCHAR *const IfOperatorString[]
Definition: parser.c:13
#define FOR_RECURSIVE
Definition: cmd.h:203
static const TCHAR RedirString[][3]
Definition: parser.c:11
Definition: cmd.h:298
Definition: cmd.h:298
struct _REDIRECTION * Redirections
Definition: cmd.h:303
BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest)
Definition: cmd.c:1327
static const TCHAR OpString[][3]
Definition: parser.c:9
struct _REDIRECTION * Next
Definition: cmd.h:354
Definition: cmd.h:298
Definition: cmd.h:298
VOID EchoCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:752
VOID FreeCommand ( PARSED_COMMAND Cmd)

Definition at line 945 of file parser.c.

Referenced by Batch(), ParseBlock(), ParseCommand(), ParseCommandLine(), ParseCommandOp(), ParseFor(), ParseIf(), and ProcessInput().

946 {
947  if (Cmd->Subcommands)
948  FreeCommand(Cmd->Subcommands);
949  if (Cmd->Next)
950  FreeCommand(Cmd->Next);
952  if (Cmd->Type == C_IF)
953  {
954  cmd_free(Cmd->If.LeftArg);
955  cmd_free(Cmd->If.RightArg);
956  }
957  else if (Cmd->Type == C_FOR)
958  {
959  cmd_free(Cmd->For.Params);
960  cmd_free(Cmd->For.List);
961  }
962  cmd_free(Cmd);
963 }
struct _PARSED_COMMAND * Subcommands
Definition: cmd.h:301
BYTE Type
Definition: cmd.h:304
struct _PARSED_COMMAND::@51::@55 For
struct _PARSED_COMMAND::@51::@54 If
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:945
struct _PARSED_COMMAND * Next
Definition: cmd.h:302
Definition: cmd.h:298
Definition: cmd.h:298
struct _REDIRECTION * Redirections
Definition: cmd.h:303
#define cmd_free(ptr)
Definition: cmddbg.h:31
VOID FreeRedirection(REDIRECTION *)
Definition: redir.c:153
static BOOL IsSeparator ( TCHAR  Char)
static

Definition at line 33 of file parser.c.

Referenced by ParsePrimary(), and ParseToken().

34 {
35  return _istspace(Char) || (Char && _tcschr(STANDARD_SEPS, Char));
36 }
char Char
Definition: bzip2.c:161
_TCHAR * _tcschr(const _TCHAR *s, _XINT c)
Definition: tcschr.h:4
#define STANDARD_SEPS
Definition: parser.c:31
#define _istspace
Definition: tchar.h:1504
static PARSED_COMMAND* ParseBlock ( REDIRECTION RedirList)
static

Definition at line 291 of file parser.c.

Referenced by ParsePrimary().

292 {
293  PARSED_COMMAND *Cmd, *Sub, **NextPtr;
294  Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
295  Cmd->Type = C_BLOCK;
296  Cmd->Next = NULL;
297  Cmd->Subcommands = NULL;
298  Cmd->Redirections = RedirList;
299 
300  /* Read the block contents */
301  NextPtr = &Cmd->Subcommands;
302  InsideBlock++;
303  while (1)
304  {
306  if (Sub)
307  {
308  *NextPtr = Sub;
309  NextPtr = &Sub->Next;
310  }
311  else if (bParseError)
312  {
313  InsideBlock--;
314  FreeCommand(Cmd);
315  return NULL;
316  }
317 
319  break;
320  /* Skip past the \n */
321  ParseChar();
322  }
323  InsideBlock--;
324 
325  /* Process any trailing redirections */
327  {
328  if (!ParseRedirection(&Cmd->Redirections))
329  {
330  FreeCommand(Cmd);
331  return NULL;
332  }
333  }
334  return Cmd;
335 }
static int CurrentTokenType
Definition: parser.c:55
struct _PARSED_COMMAND * Subcommands
Definition: cmd.h:301
BYTE Type
Definition: cmd.h:304
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:945
static TCHAR ParseChar()
Definition: parser.c:58
struct _PARSED_COMMAND * Next
Definition: cmd.h:302
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:104
#define C_OP_LOWEST
Definition: parser.c:7
static BOOL ParseRedirection(REDIRECTION **List)
Definition: parser.c:224
static BOOL bParseError
Definition: parser.c:48
smooth NULL
Definition: ftsmooth.c:557
Definition: sacdrv.h:278
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:668
Definition: cmd.h:298
struct _REDIRECTION * Redirections
Definition: cmd.h:303
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
static int InsideBlock
Definition: parser.c:56
static TCHAR ParseChar ( )
static

Definition at line 58 of file parser.c.

Referenced by ParseBlock(), ParsePrimary(), ParseRem(), and ParseToken().

59 {
60  TCHAR Char;
61 
62  if (bParseError)
63  return CurChar = 0;
64 
65 restart:
66  /*
67  * Although CRs can be injected into a line via an environment
68  * variable substitution, the parser ignores them - they won't
69  * even separate tokens.
70  */
71  do
72  Char = *ParsePos++;
73  while (Char == _T('\r'));
74 
75  if (!Char)
76  {
77  ParsePos--;
79  {
80  if (!ReadLine(ParseLine, TRUE))
81  {
82  /* ^C pressed, or line was too long */
83  bParseError = TRUE;
84  }
85  else if (*(ParsePos = ParseLine))
86  {
87  goto restart;
88  }
89  }
90  }
91  return CurChar = Char;
92 }
#define TRUE
Definition: types.h:120
static BOOL bLineContinuations
Definition: parser.c:49
#define _T(x)
Definition: tchar.h:1542
static BOOL bParseError
Definition: parser.c:48
char Char
Definition: bzip2.c:161
void restart(int argc, const char *argv[])
Definition: cmds.c:2115
char TCHAR
Definition: xmlstorage.h:189
static TCHAR ParseLine[CMDLINE_LENGTH]
Definition: parser.c:50
static TCHAR * ParsePos
Definition: parser.c:51
BOOL ReadLine(TCHAR *commandline, BOOL bMore)
Definition: cmd.c:1390
static TCHAR CurChar
Definition: parser.c:52
PARSED_COMMAND* ParseCommand ( LPTSTR  Line)

Definition at line 707 of file parser.c.

Referenced by Batch(), ParseCommandLine(), and ProcessInput().

708 {
710 
711  if (Line)
712  {
713  if (!SubstituteVars(Line, ParseLine, _T('%')))
714  return NULL;
716  }
717  else
718  {
719  if (!ReadLine(ParseLine, FALSE))
720  return NULL;
722  }
723  bParseError = FALSE;
725  CurChar = _T(' ');
726 
728  if (Cmd)
729  {
730  if (CurrentTokenType != TOK_END)
731  ParseError();
732  if (bParseError)
733  {
734  FreeCommand(Cmd);
735  Cmd = NULL;
736  }
737  bIgnoreEcho = FALSE;
738  }
739  else
740  {
741  bIgnoreEcho = TRUE;
742  }
743  return Cmd;
744 }
static int CurrentTokenType
Definition: parser.c:55
#define TRUE
Definition: types.h:120
BOOL bIgnoreEcho
Definition: cmd.c:155
BOOL SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim)
Definition: cmd.c:1161
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:945
#define C_OP_LOWEST
Definition: parser.c:7
static BOOL bLineContinuations
Definition: parser.c:49
#define _T(x)
Definition: tchar.h:1542
static BOOL bParseError
Definition: parser.c:48
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:557
static TCHAR ParseLine[CMDLINE_LENGTH]
Definition: parser.c:50
static TCHAR * ParsePos
Definition: parser.c:51
static void ParseError()
Definition: parser.c:94
BOOL ReadLine(TCHAR *commandline, BOOL bMore)
Definition: cmd.c:1390
Definition: ncftp.h:79
Definition: sacdrv.h:278
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:668
static TCHAR CurChar
Definition: parser.c:52
Definition: parser.c:40
static PARSED_COMMAND * ParseCommandOp ( int  OpType)
static

Definition at line 668 of file parser.c.

Referenced by ParseBlock(), ParseCommand(), ParseFor(), ParseIf(), and ParsePrimary().

669 {
670  PARSED_COMMAND *Cmd, *Left, *Right;
671 
672  if (OpType == C_OP_HIGHEST)
673  Cmd = ParsePrimary();
674  else
675  Cmd = ParseCommandOp(OpType + 1);
676 
677  if (Cmd && !_tcscmp(CurrentToken, OpString[OpType - C_OP_LOWEST]))
678  {
679  Left = Cmd;
680  Right = ParseCommandOp(OpType);
681  if (!Right)
682  {
683  if (!bParseError)
684  {
685  /* & is allowed to have an empty RHS */
686  if (OpType == C_MULTI)
687  return Left;
688  ParseError();
689  }
690  FreeCommand(Left);
691  return NULL;
692  }
693 
694  Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
695  Cmd->Type = OpType;
696  Cmd->Next = NULL;
697  Cmd->Redirections = NULL;
698  Cmd->Subcommands = Left;
699  Left->Next = Right;
700  Right->Next = NULL;
701  }
702 
703  return Cmd;
704 }
struct _PARSED_COMMAND * Subcommands
Definition: cmd.h:301
static TCHAR CurrentToken[CMDLINE_LENGTH]
Definition: parser.c:54
int _tcscmp(const _TCHAR *s1, const _TCHAR *s2)
Definition: tcscmp.h:8
BYTE Type
Definition: cmd.h:304
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:945
struct _PARSED_COMMAND * Next
Definition: cmd.h:302
#define C_OP_LOWEST
Definition: parser.c:7
static BOOL bParseError
Definition: parser.c:48
smooth NULL
Definition: ftsmooth.c:557
static void ParseError()
Definition: parser.c:94
Definition: sacdrv.h:278
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:668
Definition: cmd.h:298
struct _REDIRECTION * Redirections
Definition: cmd.h:303
#define cmd_alloc(size)
Definition: cmddbg.h:29
static const TCHAR OpString[][3]
Definition: parser.c:9
#define C_OP_HIGHEST
Definition: parser.c:8
static PARSED_COMMAND * ParsePrimary(void)
Definition: parser.c:611
static DECLSPEC_NOINLINE PARSED_COMMAND* ParseCommandPart ( REDIRECTION RedirList)
static

Definition at line 546 of file parser.c.

Referenced by ParsePrimary().

547 {
548  TCHAR ParsedLine[CMDLINE_LENGTH];
550  PARSED_COMMAND *(*Func)(void);
551 
552  TCHAR *Pos = _stpcpy(ParsedLine, CurrentToken) + 1;
553  DWORD_PTR TailOffset = Pos - ParsedLine;
554 
555  /* Check for special forms */
556  if ((Func = ParseFor, _tcsicmp(ParsedLine, _T("for")) == 0) ||
557  (Func = ParseIf, _tcsicmp(ParsedLine, _T("if")) == 0) ||
558  (Func = ParseRem, _tcsicmp(ParsedLine, _T("rem")) == 0))
559  {
561  /* Do special parsing only if it's not followed by /? */
562  if (_tcscmp(CurrentToken, _T("/?")) != 0)
563  {
564  if (RedirList)
565  {
566  ParseError();
567  FreeRedirection(RedirList);
568  return NULL;
569  }
570  return Func();
571  }
572  Pos = _stpcpy(Pos, _T(" /?"));
573  }
574 
575  /* Now get the tail */
576  while (1)
577  {
578  int Type = ParseToken(0, NULL);
579  if (Type == TOK_NORMAL)
580  {
581  if (Pos + _tcslen(CurrentToken) >= &ParsedLine[CMDLINE_LENGTH])
582  {
583  ParseError();
584  FreeRedirection(RedirList);
585  return NULL;
586  }
587  Pos = _stpcpy(Pos, CurrentToken);
588  }
589  else if (Type == TOK_REDIRECTION)
590  {
591  if (!ParseRedirection(&RedirList))
592  return NULL;
593  }
594  else
595  {
596  break;
597  }
598  }
599  *Pos++ = _T('\0');
600 
601  Cmd = cmd_alloc(FIELD_OFFSET(PARSED_COMMAND, Command.First[Pos - ParsedLine]));
602  Cmd->Type = C_COMMAND;
603  Cmd->Next = NULL;
604  Cmd->Subcommands = NULL;
605  Cmd->Redirections = RedirList;
606  memcpy(Cmd->Command.First, ParsedLine, (Pos - ParsedLine) * sizeof(TCHAR));
607  Cmd->Command.Rest = Cmd->Command.First + TailOffset;
608  return Cmd;
609 }
Type
Definition: Type.h:6
struct _PARSED_COMMAND * Subcommands
Definition: cmd.h:301
#define _tcsicmp
Definition: xmlstorage.h:205
static TCHAR CurrentToken[CMDLINE_LENGTH]
Definition: parser.c:54
int _tcscmp(const _TCHAR *s1, const _TCHAR *s2)
Definition: tcscmp.h:8
BYTE Type
Definition: cmd.h:304
ush Pos
Definition: deflate.h:92
#define CMDLINE_LENGTH
Definition: help.h:12
struct _PARSED_COMMAND::@51::@53 Command
Definition: shell.h:41
struct _PARSED_COMMAND * Next
Definition: cmd.h:302
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:104
static PARSED_COMMAND * ParseFor(void)
Definition: parser.c:430
static BOOL ParseRedirection(REDIRECTION **List)
Definition: parser.c:224
LPTSTR _stpcpy(LPTSTR, LPCTSTR)
Definition: misc.c:445
#define _T(x)
Definition: tchar.h:1542
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:47
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:557
static PARSED_COMMAND * ParseIf(void)
Definition: parser.c:338
char TCHAR
Definition: xmlstorage.h:189
static PARSED_COMMAND * ParseRem(void)
Definition: parser.c:538
void(* Func)(int)
static void ParseError()
Definition: parser.c:94
Definition: sacdrv.h:278
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
uint32_t DWORD_PTR
Definition: typedefs.h:63
struct _REDIRECTION * Redirections
Definition: cmd.h:303
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
VOID FreeRedirection(REDIRECTION *)
Definition: redir.c:153
Definition: cmd.h:298
static void ParseError ( )
static

Definition at line 94 of file parser.c.

Referenced by ParseCommand(), ParseCommandOp(), ParseCommandPart(), ParseFor(), ParseIf(), ParsePrimary(), and ParseRedirection().

95 {
97  bParseError = TRUE;
98 }
static int CurrentTokenType
Definition: parser.c:55
#define TRUE
Definition: types.h:120
static TCHAR CurrentToken[CMDLINE_LENGTH]
Definition: parser.c:54
static BOOL bParseError
Definition: parser.c:48
smooth NULL
Definition: ftsmooth.c:557
VOID error_syntax(LPTSTR)
Definition: error.c:150
Definition: parser.c:40
static PARSED_COMMAND* ParseFor ( void  )
static

Definition at line 430 of file parser.c.

Referenced by ParseCommandPart().

431 {
434  TCHAR *Pos = List;
435 
436  memset(Cmd, 0, sizeof(PARSED_COMMAND));
437  Cmd->Type = C_FOR;
438 
439  while (1)
440  {
441  if (_tcsicmp(CurrentToken, _T("/D")) == 0)
442  Cmd->For.Switches |= FOR_DIRS;
443  else if (_tcsicmp(CurrentToken, _T("/F")) == 0)
444  {
445  Cmd->For.Switches |= FOR_F;
446  if (!Cmd->For.Params)
447  {
449  if (CurrentToken[0] == _T('/') || CurrentToken[0] == _T('%'))
450  break;
451  Cmd->For.Params = cmd_dup(CurrentToken);
452  }
453  }
454  else if (_tcsicmp(CurrentToken, _T("/L")) == 0)
455  Cmd->For.Switches |= FOR_LOOP;
456  else if (_tcsicmp(CurrentToken, _T("/R")) == 0)
457  {
458  Cmd->For.Switches |= FOR_RECURSIVE;
459  if (!Cmd->For.Params)
460  {
462  if (CurrentToken[0] == _T('/') || CurrentToken[0] == _T('%'))
463  break;
465  Cmd->For.Params = cmd_dup(CurrentToken);
466  }
467  }
468  else
469  break;
471  }
472 
473  /* Make sure there aren't two different switches specified
474  * at the same time, unless they're /D and /R */
475  if ((Cmd->For.Switches & (Cmd->For.Switches - 1)) != 0
476  && Cmd->For.Switches != (FOR_DIRS | FOR_RECURSIVE))
477  {
478  goto error;
479  }
480 
481  /* Variable name should be % and just one other character */
482  if (CurrentToken[0] != _T('%') || _tcslen(CurrentToken) != 2)
483  goto error;
484  Cmd->For.Variable = CurrentToken[1];
485 
487  if (_tcsicmp(CurrentToken, _T("in")) != 0)
488  goto error;
489 
491  goto error;
492 
493  while (1)
494  {
495  int Type;
496 
497  /* Pretend we're inside a block so the tokenizer will stop on ')' */
498  InsideBlock++;
499  Type = ParseToken(0, STANDARD_SEPS);
500  InsideBlock--;
501 
502  if (Type == TOK_END_BLOCK)
503  break;
504 
505  if (Type != TOK_NORMAL)
506  goto error;
507 
508  if (Pos != List)
509  *Pos++ = _T(' ');
510 
511  if (Pos + _tcslen(CurrentToken) >= &List[CMDLINE_LENGTH])
512  goto error;
513  Pos = _stpcpy(Pos, CurrentToken);
514  }
515  *Pos = _T('\0');
516  Cmd->For.List = cmd_dup(List);
517 
519  if (_tcsicmp(CurrentToken, _T("do")) != 0)
520  goto error;
521 
523  if (Cmd->Subcommands == NULL)
524  {
525  FreeCommand(Cmd);
526  return NULL;
527  }
528 
529  return Cmd;
530 
531 error:
532  FreeCommand(Cmd);
533  ParseError();
534  return NULL;
535 }
#define FOR_DIRS
Definition: cmd.h:200
Type
Definition: Type.h:6
struct _PARSED_COMMAND * Subcommands
Definition: cmd.h:301
#define _tcsicmp
Definition: xmlstorage.h:205
static TCHAR CurrentToken[CMDLINE_LENGTH]
Definition: parser.c:54
BYTE Type
Definition: cmd.h:304
ush Pos
Definition: deflate.h:92
#define CMDLINE_LENGTH
Definition: help.h:12
struct _PARSED_COMMAND::@51::@55 For
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:945
static VOID StripQuotes(LPSTR in)
Definition: cmdcons.c:116
#define FOR_F
Definition: cmd.h:201
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:104
#define C_OP_LOWEST
Definition: parser.c:7
LPTSTR _stpcpy(LPTSTR, LPCTSTR)
Definition: misc.c:445
#define _T(x)
Definition: tchar.h:1542
#define FOR_LOOP
Definition: cmd.h:202
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:557
Definition: cmd.h:298
char TCHAR
Definition: xmlstorage.h:189
LIST_ENTRY List
Definition: psmgr.c:57
DWORD error
Definition: parser.c:104
static void ParseError()
Definition: parser.c:94
#define FOR_RECURSIVE
Definition: cmd.h:203
Definition: sacdrv.h:278
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:668
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
#define cmd_dup(str)
Definition: cmddbg.h:32
static int InsideBlock
Definition: parser.c:56
#define memset(x, y, z)
Definition: compat.h:39
static PARSED_COMMAND* ParseIf ( void  )
static

Definition at line 338 of file parser.c.

Referenced by ParseCommandPart().

339 {
341  int Type;
342  memset(Cmd, 0, sizeof(PARSED_COMMAND));
343  Cmd->Type = C_IF;
344 
345  Type = CurrentTokenType;
346  if (_tcsicmp(CurrentToken, _T("/I")) == 0)
347  {
348  Cmd->If.Flags |= IFFLAG_IGNORECASE;
349  Type = ParseToken(0, STANDARD_SEPS);
350  }
351  if (_tcsicmp(CurrentToken, _T("not")) == 0)
352  {
353  Cmd->If.Flags |= IFFLAG_NEGATE;
354  Type = ParseToken(0, STANDARD_SEPS);
355  }
356 
357  if (Type != TOK_NORMAL)
358  {
359  FreeCommand(Cmd);
360  ParseError();
361  return NULL;
362  }
363 
364  /* Check for unary operators */
365  for (; Cmd->If.Operator <= IF_MAX_UNARY; Cmd->If.Operator++)
366  {
367  if (_tcsicmp(CurrentToken, IfOperatorString[Cmd->If.Operator]) == 0)
368  {
370  {
371  FreeCommand(Cmd);
372  ParseError();
373  return NULL;
374  }
375  Cmd->If.RightArg = cmd_dup(CurrentToken);
376  goto condition_done;
377  }
378  }
379 
380  /* It must be a two-argument (comparison) operator. It could be ==, so
381  * the equals sign can't be treated as whitespace here. */
382  Cmd->If.LeftArg = cmd_dup(CurrentToken);
383  ParseToken(0, _T(",;"));
384 
385  /* The right argument can come immediately after == */
386  if (_tcsnicmp(CurrentToken, _T("=="), 2) == 0 && CurrentToken[2])
387  {
388  Cmd->If.RightArg = cmd_dup(&CurrentToken[2]);
389  goto condition_done;
390  }
391 
392  for (; Cmd->If.Operator <= IF_MAX_COMPARISON; Cmd->If.Operator++)
393  {
394  if (_tcsicmp(CurrentToken, IfOperatorString[Cmd->If.Operator]) == 0)
395  {
397  break;
398  Cmd->If.RightArg = cmd_dup(CurrentToken);
399  goto condition_done;
400  }
401  }
402  FreeCommand(Cmd);
403  ParseError();
404  return NULL;
405 
406 condition_done:
408  if (Cmd->Subcommands == NULL)
409  {
410  FreeCommand(Cmd);
411  return NULL;
412  }
413  if (_tcsicmp(CurrentToken, _T("else")) == 0)
414  {
416  if (Cmd->Subcommands->Next == NULL)
417  {
418  FreeCommand(Cmd);
419  return NULL;
420  }
421  }
422 
423  return Cmd;
424 }
static int CurrentTokenType
Definition: parser.c:55
Type
Definition: Type.h:6
struct _PARSED_COMMAND * Subcommands
Definition: cmd.h:301
#define _tcsicmp
Definition: xmlstorage.h:205
#define IFFLAG_IGNORECASE
Definition: cmd.h:227
static TCHAR CurrentToken[CMDLINE_LENGTH]
Definition: parser.c:54
BYTE Type
Definition: cmd.h:304
#define IF_MAX_UNARY
struct _PARSED_COMMAND::@51::@54 If
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:945
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:104
#define C_OP_LOWEST
Definition: parser.c:7
#define _T(x)
Definition: tchar.h:1542
#define _tcsnicmp
Definition: xmlstorage.h:207
smooth NULL
Definition: ftsmooth.c:557
Definition: cmd.h:298
#define IFFLAG_NEGATE
Definition: cmd.h:226
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
static const TCHAR *const IfOperatorString[]
Definition: parser.c:13
static void ParseError()
Definition: parser.c:94
Definition: sacdrv.h:278
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:668
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
#define cmd_dup(str)
Definition: cmddbg.h:32
#define IF_MAX_COMPARISON
#define memset(x, y, z)
Definition: compat.h:39
static PARSED_COMMAND* ParsePrimary ( void  )
static

Definition at line 611 of file parser.c.

Referenced by ParseCommandOp().

612 {
613  REDIRECTION *RedirList = NULL;
614  int Type;
615 
616  while (IsSeparator(CurChar))
617  {
618  if (CurChar == _T('\n'))
619  return NULL;
620  ParseChar();
621  }
622 
623  if (!CurChar)
624  return NULL;
625 
626  if (CurChar == _T(':'))
627  {
628  /* "Ignore" the rest of the line.
629  * (Line continuations will still be parsed, though.) */
630  while (ParseToken(0, NULL) != TOK_END)
631  ;
632  return NULL;
633  }
634 
635  if (CurChar == _T('@'))
636  {
638  ParseChar();
639  Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
640  Cmd->Type = C_QUIET;
641  Cmd->Next = NULL;
642  /* @ acts like a unary operator with low precedence,
643  * so call the top-level parser */
645  Cmd->Redirections = NULL;
646  return Cmd;
647  }
648 
649  /* Process leading redirections and get the head of the command */
650  while ((Type = ParseToken(_T('('), STANDARD_SEPS)) == TOK_REDIRECTION)
651  {
652  if (!ParseRedirection(&RedirList))
653  return NULL;
654  }
655 
656  if (Type == TOK_NORMAL)
657  return ParseCommandPart(RedirList);
658  else if (Type == TOK_BEGIN_BLOCK)
659  return ParseBlock(RedirList);
660  else if (Type == TOK_END_BLOCK && !RedirList)
661  return NULL;
662 
663  ParseError();
664  FreeRedirection(RedirList);
665  return NULL;
666 }
static DECLSPEC_NOINLINE PARSED_COMMAND * ParseCommandPart(REDIRECTION *RedirList)
Definition: parser.c:546
Definition: cmd.h:298
Type
Definition: Type.h:6
struct _PARSED_COMMAND * Subcommands
Definition: cmd.h:301
BYTE Type
Definition: cmd.h:304
static PARSED_COMMAND * ParseBlock(REDIRECTION *RedirList)
Definition: parser.c:291
static BOOL IsSeparator(TCHAR Char)
Definition: parser.c:33
static TCHAR ParseChar()
Definition: parser.c:58
struct _PARSED_COMMAND * Next
Definition: cmd.h:302
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:104
#define C_OP_LOWEST
Definition: parser.c:7
static BOOL ParseRedirection(REDIRECTION **List)
Definition: parser.c:224
#define _T(x)
Definition: tchar.h:1542
smooth NULL
Definition: ftsmooth.c:557
static void ParseError()
Definition: parser.c:94
Definition: sacdrv.h:278
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:668
struct _REDIRECTION * Redirections
Definition: cmd.h:303
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
static TCHAR CurChar
Definition: parser.c:52
VOID FreeRedirection(REDIRECTION *)
Definition: redir.c:153
Definition: parser.c:40
static BOOL ParseRedirection ( REDIRECTION **  List)
static

Definition at line 224 of file parser.c.

Referenced by ParseBlock(), ParseCommandPart(), and ParsePrimary().

225 {
226  TCHAR *Tok = CurrentToken;
227  BYTE Number;
228  REDIR_MODE RedirMode;
229  REDIRECTION *Redir;
230 
231  if (*Tok >= _T('0') && *Tok <= _T('9'))
232  Number = *Tok++ - _T('0');
233  else
234  Number = *Tok == _T('<') ? 0 : 1;
235 
236  if (*Tok++ == _T('<'))
237  {
238  RedirMode = REDIR_READ;
239  if (*Tok == _T('<'))
240  goto fail;
241  }
242  else
243  {
244  RedirMode = REDIR_WRITE;
245  if (*Tok == _T('>'))
246  {
247  RedirMode = REDIR_APPEND;
248  Tok++;
249  }
250  }
251 
252  if (!*Tok)
253  {
254  /* The file name was not part of this token, so it'll be the next one */
256  goto fail;
257  Tok = CurrentToken;
258  }
259 
260  /* If a redirection for this handle number already exists, delete it */
261  while ((Redir = *List))
262  {
263  if (Redir->Number == Number)
264  {
265  *List = Redir->Next;
266  cmd_free(Redir);
267  continue;
268  }
269  List = &Redir->Next;
270  }
271 
272  Redir = cmd_alloc(FIELD_OFFSET(REDIRECTION, Filename[_tcslen(Tok) + 1]));
273  Redir->Next = NULL;
275  Redir->Number = Number;
276  Redir->Mode = RedirMode;
277  _tcscpy(Redir->Filename, Tok);
278  *List = Redir;
279  return TRUE;
280 
281 fail:
282  ParseError();
283  FreeRedirection(*List);
284  *List = NULL;
285  return FALSE;
286 }
#define TRUE
Definition: types.h:120
enum _REDIR_MODE REDIR_MODE
static TCHAR CurrentToken[CMDLINE_LENGTH]
Definition: parser.c:54
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
_TCHAR * _tcscpy(_TCHAR *to, const _TCHAR *from)
Definition: tcscpy.h:8
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:104
REDIR_MODE Mode
Definition: cmd.h:357
HANDLE OldHandle
Definition: cmd.h:355
#define _T(x)
Definition: tchar.h:1542
#define FALSE
Definition: types.h:117
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:557
BYTE Number
Definition: cmd.h:356
char TCHAR
Definition: xmlstorage.h:189
TCHAR Filename[]
Definition: cmd.h:358
static void ParseError()
Definition: parser.c:94
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
unsigned char BYTE
Definition: ntddk_ex.h:96
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
#define cmd_free(ptr)
Definition: cmddbg.h:31
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
VOID FreeRedirection(REDIRECTION *)
Definition: redir.c:153
struct _REDIRECTION * Next
Definition: cmd.h:354
static PARSED_COMMAND* ParseRem ( void  )
static

Definition at line 538 of file parser.c.

Referenced by ParseCommandPart().

539 {
540  /* Just ignore the rest of the line */
541  while (CurChar && CurChar != _T('\n'))
542  ParseChar();
543  return NULL;
544 }
static TCHAR ParseChar()
Definition: parser.c:58
#define _T(x)
Definition: tchar.h:1542
smooth NULL
Definition: ftsmooth.c:557
static TCHAR CurChar
Definition: parser.c:52
static int ParseToken ( TCHAR  ExtraEnd,
TCHAR Separators 
)
static

Definition at line 104 of file parser.c.

Referenced by ParseBlock(), ParseCommandPart(), ParseFor(), ParseIf(), ParsePrimary(), and ParseRedirection().

105 {
107  TCHAR Char;
108  int Type;
109  BOOL bInQuote = FALSE;
110 
111  for (Char = CurChar; Char && Char != _T('\n'); Char = ParseChar())
112  {
113  bInQuote ^= (Char == _T('"'));
114  if (!bInQuote)
115  {
116  if (Separators != NULL)
117  {
118  if (_istspace(Char) || _tcschr(Separators, Char))
119  {
120  /* Skip leading separators */
121  if (Out == CurrentToken)
122  continue;
123  break;
124  }
125  }
126 
127  /* Check for numbered redirection */
128  if ((Char >= _T('0') && Char <= _T('9') &&
129  (ParsePos == &ParseLine[1] || IsSeparator(ParsePos[-2]))
130  && (*ParsePos == _T('<') || *ParsePos == _T('>'))))
131  {
132  break;
133  }
134 
135  if (Char == ExtraEnd)
136  break;
137  if (InsideBlock && Char == _T(')'))
138  break;
139  if (_tcschr(_T("&|<>"), Char))
140  break;
141 
142  if (Char == _T('^'))
143  {
144  Char = ParseChar();
145  /* Eat up a \n, allowing line continuation */
146  if (Char == _T('\n'))
147  Char = ParseChar();
148  /* Next character is a forced literal */
149  }
150  }
151  if (Out == &CurrentToken[CMDLINE_LENGTH - 1])
152  break;
153  *Out++ = Char;
154  }
155 
156  /* Check if we got at least one character before reaching a special one.
157  * If so, return them and leave the special for the next call. */
158  if (Out != CurrentToken)
159  {
160  Type = TOK_NORMAL;
161  }
162  else if (Char == _T('('))
163  {
164  Type = TOK_BEGIN_BLOCK;
165  *Out++ = Char;
166  ParseChar();
167  }
168  else if (Char == _T(')'))
169  {
170  Type = TOK_END_BLOCK;
171  *Out++ = Char;
172  ParseChar();
173  }
174  else if (Char == _T('&') || Char == _T('|'))
175  {
176  Type = TOK_OPERATOR;
177  *Out++ = Char;
178  Char = ParseChar();
179  /* check for && or || */
180  if (Char == Out[-1])
181  {
182  *Out++ = Char;
183  ParseChar();
184  }
185  }
186  else if ((Char >= _T('0') && Char <= _T('9'))
187  || (Char == _T('<') || Char == _T('>')))
188  {
189  Type = TOK_REDIRECTION;
190  if (Char >= _T('0') && Char <= _T('9'))
191  {
192  *Out++ = Char;
193  Char = ParseChar();
194  }
195  *Out++ = Char;
196  Char = ParseChar();
197  if (Char == Out[-1])
198  {
199  /* Strangely, the tokenizer allows << as well as >>... (it
200  * will cause an error when trying to parse it though) */
201  *Out++ = Char;
202  Char = ParseChar();
203  }
204  if (Char == _T('&'))
205  {
206  *Out++ = Char;
207  while (IsSeparator(Char = ParseChar()))
208  ;
209  if (Char >= _T('0') && Char <= _T('9'))
210  {
211  *Out++ = Char;
212  ParseChar();
213  }
214  }
215  }
216  else
217  {
218  Type = TOK_END;
219  }
220  *Out = _T('\0');
221  return CurrentTokenType = Type;
222 }
static int CurrentTokenType
Definition: parser.c:55
Type
Definition: Type.h:6
static TCHAR CurrentToken[CMDLINE_LENGTH]
Definition: parser.c:54
#define CMDLINE_LENGTH
Definition: help.h:12
static BOOL IsSeparator(TCHAR Char)
Definition: parser.c:33
static TCHAR ParseChar()
Definition: parser.c:58
#define _T(x)
Definition: tchar.h:1542
#define FALSE
Definition: types.h:117
char Char
Definition: bzip2.c:161
smooth NULL
Definition: ftsmooth.c:557
_TCHAR * _tcschr(const _TCHAR *s, _XINT c)
Definition: tcschr.h:4
char TCHAR
Definition: xmlstorage.h:189
unsigned int BOOL
Definition: ntddk_ex.h:94
static TCHAR ParseLine[CMDLINE_LENGTH]
Definition: parser.c:50
static TCHAR * ParsePos
Definition: parser.c:51
static TCHAR CurChar
Definition: parser.c:52
static int InsideBlock
Definition: parser.c:56
#define _istspace
Definition: tchar.h:1504
Definition: parser.c:40
TCHAR* Unparse ( PARSED_COMMAND Cmd,
TCHAR Out,
TCHAR OutEnd 
)

Definition at line 844 of file parser.c.

Referenced by ExecuteAsync().

845 {
846  TCHAR Buf[CMDLINE_LENGTH];
847  PARSED_COMMAND *Sub;
848  REDIRECTION *Redir;
849 
850 /*
851  * Since this function has the annoying requirement that it must avoid
852  * overflowing the supplied buffer, define some helper macros to make
853  * this less painful.
854  */
855 #define CHAR(Char) { \
856  if (Out == OutEnd) return NULL; \
857  *Out++ = Char; }
858 #define STRING(String) { \
859  if (Out + _tcslen(String) > OutEnd) return NULL; \
860  Out = _stpcpy(Out, String); }
861 #define PRINTF(Format, ...) { \
862  UINT Len = _sntprintf(Out, OutEnd - Out, Format, __VA_ARGS__); \
863  if (Len > (UINT)(OutEnd - Out)) return NULL; \
864  Out += Len; }
865 #define RECURSE(Subcommand) { \
866  Out = Unparse(Subcommand, Out, OutEnd); \
867  if (!Out) return NULL; }
868 
869  switch (Cmd->Type)
870  {
871  case C_COMMAND:
872  /* This is fragile since there could be special characters, but
873  * Windows doesn't bother escaping them, so for compatibility
874  * we probably shouldn't do it either */
875  if (!SubstituteForVars(Cmd->Command.First, Buf)) return NULL;
876  STRING(Buf)
877  if (!SubstituteForVars(Cmd->Command.Rest, Buf)) return NULL;
878  STRING(Buf)
879  break;
880  case C_QUIET:
881  CHAR(_T('@'))
882  RECURSE(Cmd->Subcommands)
883  break;
884  case C_BLOCK:
885  CHAR(_T('('))
886  for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
887  {
888  RECURSE(Sub)
889  if (Sub->Next)
890  CHAR(_T('&'))
891  }
892  CHAR(_T(')'))
893  break;
894  case C_MULTI:
895  case C_IFFAILURE:
896  case C_IFSUCCESS:
897  case C_PIPE:
898  Sub = Cmd->Subcommands;
899  RECURSE(Sub)
900  PRINTF(_T(" %s "), OpString[Cmd->Type - C_OP_LOWEST])
901  RECURSE(Sub->Next)
902  break;
903  case C_IF:
904  STRING(_T("if"))
905  if (Cmd->If.Flags & IFFLAG_IGNORECASE)
906  STRING(_T(" /I"))
907  if (Cmd->If.Flags & IFFLAG_NEGATE)
908  STRING(_T(" not"))
909  if (Cmd->If.LeftArg && SubstituteForVars(Cmd->If.LeftArg, Buf))
910  PRINTF(_T(" %s"), Buf)
911  PRINTF(_T(" %s"), IfOperatorString[Cmd->If.Operator]);
912  if (!SubstituteForVars(Cmd->If.RightArg, Buf)) return NULL;
913  PRINTF(_T(" %s "), Buf)
914  Sub = Cmd->Subcommands;
915  RECURSE(Sub)
916  if (Sub->Next)
917  {
918  STRING(_T(" else "))
919  RECURSE(Sub->Next)
920  }
921  break;
922  case C_FOR:
923  STRING(_T("for"))
924  if (Cmd->For.Switches & FOR_DIRS) STRING(_T(" /D"))
925  if (Cmd->For.Switches & FOR_F) STRING(_T(" /F"))
926  if (Cmd->For.Switches & FOR_LOOP) STRING(_T(" /L"))
927  if (Cmd->For.Switches & FOR_RECURSIVE) STRING(_T(" /R"))
928  if (Cmd->For.Params)
929  PRINTF(_T(" %s"), Cmd->For.Params)
930  PRINTF(_T(" %%%c in (%s) do "), Cmd->For.Variable, Cmd->For.List)
931  RECURSE(Cmd->Subcommands)
932  break;
933  }
934 
935  for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
936  {
937  if (!SubstituteForVars(Redir->Filename, Buf)) return NULL;
938  PRINTF(_T(" %c%s%s"), _T('0') + Redir->Number,
939  RedirString[Redir->Mode], Buf)
940  }
941  return Out;
942 }
#define FOR_DIRS
Definition: cmd.h:200
Definition: cmd.h:298
Type
Definition: Type.h:6
#define RECURSE(Subcommand)
Definition: bidi.c:75
#define IFFLAG_IGNORECASE
Definition: cmd.h:227
BYTE Type
Definition: cmd.h:304
char CHAR
Definition: xmlstorage.h:175
#define CMDLINE_LENGTH
Definition: help.h:12
struct _PARSED_COMMAND::@51::@53 Command
Definition: shell.h:41
#define FOR_F
Definition: cmd.h:201
#define C_OP_LOWEST
Definition: parser.c:7
REDIR_MODE Mode
Definition: cmd.h:357
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define _T(x)
Definition: tchar.h:1542
#define PRINTF(Format,...)
#define FOR_LOOP
Definition: cmd.h:202
#define F(i)
Definition: internal.h:87
smooth NULL
Definition: ftsmooth.c:557
Definition: cmd.h:298
return(0)
Definition: cmd.h:298
BYTE Number
Definition: cmd.h:356
char TCHAR
Definition: xmlstorage.h:189
LIST_ENTRY List
Definition: psmgr.c:57
if(!(yy_init))
Definition: macro.lex.yy.c:704
#define D
Definition: mbstring.h:29
const GLubyte * c
Definition: glext.h:8905
#define IFFLAG_NEGATE
Definition: cmd.h:226
TCHAR Filename[]
Definition: cmd.h:358
#define for
Definition: utility.h:88
static const TCHAR *const IfOperatorString[]
Definition: parser.c:13
#define STRING(String)
std::wstring STRING
Definition: fontsub.cpp:33
#define FOR_RECURSIVE
Definition: cmd.h:203
static const TCHAR RedirString[][3]
Definition: parser.c:11
#define I(s)
GLdouble s
Definition: gl.h:2039
Definition: cmd.h:298
GLfloat CONST GLvector4f * in
Definition: m_xform.h:122
Definition: cmd.h:298
BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest)
Definition: cmd.c:1327
static const TCHAR OpString[][3]
Definition: parser.c:9
Definition: cmd.h:298
Definition: cmd.h:298
Definition: bidi.c:76

Variable Documentation

BOOL bLineContinuations
static

Definition at line 49 of file parser.c.

Referenced by ParseChar(), and ParseCommand().

BOOL bParseError
static

Definition at line 48 of file parser.c.

Referenced by ParseBlock(), ParseChar(), ParseCommand(), ParseCommandOp(), and ParseError().

TCHAR CurrentToken[CMDLINE_LENGTH]
static
int CurrentTokenType
static

Definition at line 55 of file parser.c.

Referenced by ParseBlock(), ParseCommand(), ParseError(), ParseIf(), and ParseToken().

const TCHAR* const IfOperatorString[]
static
Initial value:
=
{
_T("cmdextversion"),
_T("defined"),
_T("errorlevel"),
_T("exist"),
#define IF_MAX_UNARY
_T("=="),
_T("equ"),
_T("gtr"),
_T("geq"),
_T("lss"),
_T("leq"),
_T("neq"),
#define IF_MAX_COMPARISON
}
#define _T(x)
Definition: tchar.h:1542

Definition at line 13 of file parser.c.

Referenced by EchoCommand(), ParseIf(), and Unparse().

int InsideBlock
static

Definition at line 56 of file parser.c.

Referenced by ParseBlock(), ParseFor(), and ParseToken().

const TCHAR OpString[][3] = { _T("&"), _T("||"), _T("&&"), _T("|") }
static

Definition at line 9 of file parser.c.

Referenced by EchoCommand(), ParseCommandOp(), and Unparse().

TCHAR ParseLine[CMDLINE_LENGTH]
static

Definition at line 50 of file parser.c.

Referenced by ParseChar(), ParseCommand(), and ParseToken().

TCHAR* ParsePos
static

Definition at line 51 of file parser.c.

Referenced by ParseChar(), ParseCommand(), and ParseToken().

const TCHAR RedirString[][3] = { _T("<"), _T(">"), _T(">>") }
static

Definition at line 11 of file parser.c.

Referenced by EchoCommand(), and Unparse().