ReactOS  0.4.14-dev-606-g14ebc0b
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 (void)
 
static void ParseError (void)
 
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_COMMANDParseCommandPart (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

◆ C_OP_HIGHEST

#define C_OP_HIGHEST   C_PIPE

Definition at line 8 of file parser.c.

◆ C_OP_LOWEST

#define C_OP_LOWEST   C_MULTI

Definition at line 7 of file parser.c.

◆ CHAR

#define CHAR (   Char)
Value:
do { \
if (Out == OutEnd) return NULL; \
*Out++ = Char; \
} while (0)
smooth NULL
Definition: ftsmooth.c:416

◆ IF_MAX_COMPARISON

#define IF_MAX_COMPARISON   IF_NEQ

◆ IF_MAX_UNARY

#define IF_MAX_UNARY   IF_EXIST

◆ PRINTF

#define PRINTF (   Format,
  ... 
)
Value:
do { \
UINT Len = _sntprintf(Out, OutEnd - Out, Format, __VA_ARGS__); \
if (Len > (UINT)(OutEnd - Out)) return NULL; \
Out += Len; \
} while (0)
smooth NULL
Definition: ftsmooth.c:416
#define Len
Definition: deflate.h:82
#define _sntprintf
Definition: xmlstorage.h:201
unsigned int UINT
Definition: ndis.h:50

◆ RECURSE

#define RECURSE (   Subcommand)
Value:
do { \
Out = Unparse(Subcommand, Out, OutEnd); \
if (!Out) return NULL; \
} while (0)
smooth NULL
Definition: ftsmooth.c:416
TCHAR * Unparse(PARSED_COMMAND *Cmd, TCHAR *Out, TCHAR *OutEnd)
Definition: parser.c:905

◆ STANDARD_SEPS

#define STANDARD_SEPS   _T(",;=")

Definition at line 31 of file parser.c.

◆ STRING

Value:
do { \
if (Out + _tcslen(String) > OutEnd) return NULL; \
Out = _stpcpy(Out, String); \
} while (0)
static WCHAR String[]
Definition: stringtable.c:55
LPTSTR _stpcpy(LPTSTR, LPCTSTR)
Definition: misc.c:461
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:416

Enumeration Type Documentation

◆ anonymous enum

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

◆ EchoCommand()

VOID EchoCommand ( PARSED_COMMAND Cmd)

Definition at line 811 of file parser.c.

812 {
813  TCHAR Buf[CMDLINE_LENGTH];
814  PARSED_COMMAND *Sub;
815  REDIRECTION *Redir;
816 
817  switch (Cmd->Type)
818  {
819  case C_COMMAND:
820  if (SubstituteForVars(Cmd->Command.First, Buf))
821  ConOutPrintf(_T("%s"), Buf);
822  if (SubstituteForVars(Cmd->Command.Rest, Buf))
823  ConOutPrintf(_T("%s"), Buf);
824  break;
825  case C_QUIET:
826  return;
827  case C_BLOCK:
828  ConOutChar(_T('('));
829  Sub = Cmd->Subcommands;
830  if (Sub && !Sub->Next)
831  {
832  /* Single-command block: display all on one line */
833  EchoCommand(Sub);
834  }
835  else if (Sub)
836  {
837  /* Multi-command block: display parenthesis on separate lines */
838  ConOutChar(_T('\n'));
839  do
840  {
841  EchoCommand(Sub);
842  ConOutChar(_T('\n'));
843  Sub = Sub->Next;
844  } while (Sub);
845  }
846  ConOutChar(_T(')'));
847  break;
848  case C_MULTI:
849  case C_IFFAILURE:
850  case C_IFSUCCESS:
851  case C_PIPE:
852  Sub = Cmd->Subcommands;
853  EchoCommand(Sub);
854  ConOutPrintf(_T(" %s "), OpString[Cmd->Type - C_OP_LOWEST]);
855  EchoCommand(Sub->Next);
856  break;
857  case C_IF:
858  ConOutPrintf(_T("if"));
859  if (Cmd->If.Flags & IFFLAG_IGNORECASE)
860  ConOutPrintf(_T(" /I"));
861  if (Cmd->If.Flags & IFFLAG_NEGATE)
862  ConOutPrintf(_T(" not"));
863  if (Cmd->If.LeftArg && SubstituteForVars(Cmd->If.LeftArg, Buf))
864  ConOutPrintf(_T(" %s"), Buf);
865  ConOutPrintf(_T(" %s"), IfOperatorString[Cmd->If.Operator]);
866  if (SubstituteForVars(Cmd->If.RightArg, Buf))
867  ConOutPrintf(_T(" %s "), Buf);
868  Sub = Cmd->Subcommands;
869  EchoCommand(Sub);
870  if (Sub->Next)
871  {
872  ConOutPrintf(_T(" else "));
873  EchoCommand(Sub->Next);
874  }
875  break;
876  case C_FOR:
877  ConOutPrintf(_T("for"));
878  if (Cmd->For.Switches & FOR_DIRS) ConOutPrintf(_T(" /D"));
879  if (Cmd->For.Switches & FOR_F) ConOutPrintf(_T(" /F"));
880  if (Cmd->For.Switches & FOR_LOOP) ConOutPrintf(_T(" /L"));
881  if (Cmd->For.Switches & FOR_RECURSIVE) ConOutPrintf(_T(" /R"));
882  if (Cmd->For.Params)
883  ConOutPrintf(_T(" %s"), Cmd->For.Params);
884  ConOutPrintf(_T(" %%%c in (%s) do "), Cmd->For.Variable, Cmd->For.List);
885  EchoCommand(Cmd->Subcommands);
886  break;
887  }
888 
889  for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
890  {
891  if (SubstituteForVars(Redir->Filename, Buf))
892  {
893  ConOutPrintf(_T(" %c%s%s"), _T('0') + Redir->Number,
894  RedirString[Redir->Mode], Buf);
895  }
896  }
897 }
#define FOR_DIRS
Definition: cmd.h:197
Definition: cmd.h:292
Definition: cmd.h:292
Definition: cmd.h:292
#define IFFLAG_IGNORECASE
Definition: cmd.h:224
VOID ConOutChar(TCHAR c)
Definition: console.c:123
#define CMDLINE_LENGTH
Definition: help.h:12
Definition: cmd.h:292
#define ConOutPrintf(szStr,...)
Definition: console.h:42
#define FOR_F
Definition: cmd.h:198
struct _PARSED_COMMAND * Next
Definition: cmd.h:296
#define C_OP_LOWEST
Definition: parser.c:7
REDIR_MODE Mode
Definition: cmd.h:351
#define FOR_LOOP
Definition: cmd.h:199
BYTE Number
Definition: cmd.h:350
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
Definition: cmd.h:292
#define IFFLAG_NEGATE
Definition: cmd.h:223
TCHAR Filename[]
Definition: cmd.h:352
static const TCHAR *const IfOperatorString[]
Definition: parser.c:13
#define FOR_RECURSIVE
Definition: cmd.h:200
static const TCHAR RedirString[][3]
Definition: parser.c:11
Definition: sacdrv.h:277
Definition: cmd.h:292
BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest)
Definition: cmd.c:1372
static const TCHAR OpString[][3]
Definition: parser.c:9
struct _REDIRECTION * Next
Definition: cmd.h:348
Definition: cmd.h:292
VOID EchoCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:811

Referenced by Batch(), and RunInstance().

◆ FreeCommand()

VOID FreeCommand ( PARSED_COMMAND Cmd)

Definition at line 1015 of file parser.c.

1016 {
1017  if (Cmd->Subcommands)
1018  FreeCommand(Cmd->Subcommands);
1019  if (Cmd->Next)
1020  FreeCommand(Cmd->Next);
1021  FreeRedirection(Cmd->Redirections);
1022  if (Cmd->Type == C_IF)
1023  {
1024  cmd_free(Cmd->If.LeftArg);
1025  cmd_free(Cmd->If.RightArg);
1026  }
1027  else if (Cmd->Type == C_FOR)
1028  {
1029  cmd_free(Cmd->For.Params);
1030  cmd_free(Cmd->For.List);
1031  }
1032  cmd_free(Cmd);
1033 }
Definition: cmd.h:292
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:1015
Definition: cmd.h:292
Definition: sacdrv.h:277
#define cmd_free(ptr)
Definition: cmddbg.h:31
VOID FreeRedirection(REDIRECTION *)
Definition: redir.c:153

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

◆ IsSeparator()

static BOOL IsSeparator ( TCHAR  Char)
static

Definition at line 33 of file parser.c.

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

Referenced by ParsePrimary(), and ParseToken().

◆ ParseBlock()

static PARSED_COMMAND* ParseBlock ( REDIRECTION RedirList)
static

Definition at line 298 of file parser.c.

299 {
300  PARSED_COMMAND *Cmd, *Sub, **NextPtr;
301 
302  Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
303  if (!Cmd)
304  {
305  WARN("Cannot allocate memory for Cmd!\n");
306  ParseError();
307  FreeRedirection(RedirList);
308  return NULL;
309  }
310  Cmd->Type = C_BLOCK;
311  Cmd->Next = NULL;
312  Cmd->Subcommands = NULL;
313  Cmd->Redirections = RedirList;
314 
315  /* Read the block contents */
316  NextPtr = &Cmd->Subcommands;
317  InsideBlock++;
318  while (1)
319  {
321  if (Sub)
322  {
323  *NextPtr = Sub;
324  NextPtr = &Sub->Next;
325  }
326  else if (bParseError)
327  {
328  InsideBlock--;
329  FreeCommand(Cmd);
330  return NULL;
331  }
332 
334  break;
335 
336  /* Skip past the \n */
337  ParseChar();
338  }
339  InsideBlock--;
340 
341  /* Process any trailing redirections */
343  {
344  if (!ParseRedirection(&Cmd->Redirections))
345  {
346  FreeCommand(Cmd);
347  return NULL;
348  }
349  }
350  return Cmd;
351 }
static int CurrentTokenType
Definition: parser.c:55
Definition: cmd.h:292
#define WARN(fmt,...)
Definition: debug.h:111
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:1015
struct _PARSED_COMMAND * Next
Definition: cmd.h:296
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:106
#define C_OP_LOWEST
Definition: parser.c:7
static BOOL ParseRedirection(REDIRECTION **List)
Definition: parser.c:226
static BOOL bParseError
Definition: parser.c:48
smooth NULL
Definition: ftsmooth.c:416
static TCHAR ParseChar(void)
Definition: parser.c:58
Definition: sacdrv.h:277
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:719
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
static void ParseError(void)
Definition: parser.c:96
static int InsideBlock
Definition: parser.c:56
VOID FreeRedirection(REDIRECTION *)
Definition: redir.c:153

Referenced by ParsePrimary().

◆ ParseChar()

static TCHAR ParseChar ( void  )
static

Definition at line 58 of file parser.c.

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  {
73  Char = *ParsePos++;
74  }
75  while (Char == _T('\r'));
76 
77  if (!Char)
78  {
79  ParsePos--;
81  {
82  if (!ReadLine(ParseLine, TRUE))
83  {
84  /* ^C pressed, or line was too long */
85  bParseError = TRUE;
86  }
87  else if (*(ParsePos = ParseLine))
88  {
89  goto restart;
90  }
91  }
92  }
93  return (CurChar = Char);
94 }
#define TRUE
Definition: types.h:120
static BOOL bLineContinuations
Definition: parser.c:49
static BOOL bParseError
Definition: parser.c:48
void restart(int argc, const char *argv[])
Definition: cmds.c:2115
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
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:1435
static TCHAR CurChar
Definition: parser.c:52

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

◆ ParseCommand()

PARSED_COMMAND* ParseCommand ( LPTSTR  Line)

Definition at line 766 of file parser.c.

767 {
769 
770  if (Line)
771  {
772  if (!SubstituteVars(Line, ParseLine, _T('%')))
773  return NULL;
775  }
776  else
777  {
778  if (!ReadLine(ParseLine, FALSE))
779  return NULL;
781  }
782  bParseError = FALSE;
784  CurChar = _T(' ');
785 
787  if (Cmd)
788  {
789  if (CurrentTokenType != TOK_END)
790  ParseError();
791  if (bParseError)
792  {
793  FreeCommand(Cmd);
794  Cmd = NULL;
795  }
796  bIgnoreEcho = FALSE;
797  }
798  else
799  {
800  bIgnoreEcho = TRUE;
801  }
802  return Cmd;
803 }
static int CurrentTokenType
Definition: parser.c:55
#define TRUE
Definition: types.h:120
BOOL bIgnoreEcho
Definition: cmd.c:155
Definition: parser.c:40
BOOL SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim)
Definition: cmd.c:1206
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:1015
#define C_OP_LOWEST
Definition: parser.c:7
static BOOL bLineContinuations
Definition: parser.c:49
static BOOL bParseError
Definition: parser.c:48
smooth NULL
Definition: ftsmooth.c:416
#define _T(x)
Definition: vfdio.h:22
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:1435
Definition: ncftp.h:79
Definition: sacdrv.h:277
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:719
static TCHAR CurChar
Definition: parser.c:52
static void ParseError(void)
Definition: parser.c:96

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

◆ ParseCommandOp()

static PARSED_COMMAND * ParseCommandOp ( int  OpType)
static

Definition at line 719 of file parser.c.

720 {
721  PARSED_COMMAND *Cmd, *Left, *Right;
722 
723  if (OpType == C_OP_HIGHEST)
724  Cmd = ParsePrimary();
725  else
726  Cmd = ParseCommandOp(OpType + 1);
727 
728  if (Cmd && !_tcscmp(CurrentToken, OpString[OpType - C_OP_LOWEST]))
729  {
730  Left = Cmd;
731  Right = ParseCommandOp(OpType);
732  if (!Right)
733  {
734  if (!bParseError)
735  {
736  /* & is allowed to have an empty RHS */
737  if (OpType == C_MULTI)
738  return Left;
739  ParseError();
740  }
741  FreeCommand(Left);
742  return NULL;
743  }
744 
745  Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
746  if (!Cmd)
747  {
748  WARN("Cannot allocate memory for Cmd!\n");
749  ParseError();
750  FreeCommand(Left);
751  FreeCommand(Right);
752  return NULL;
753  }
754  Cmd->Type = OpType;
755  Cmd->Next = NULL;
756  Cmd->Redirections = NULL;
757  Cmd->Subcommands = Left;
758  Left->Next = Right;
759  Right->Next = NULL;
760  }
761 
762  return Cmd;
763 }
static TCHAR CurrentToken[CMDLINE_LENGTH]
Definition: parser.c:54
int _tcscmp(const _TCHAR *s1, const _TCHAR *s2)
Definition: tcscmp.h:8
#define WARN(fmt,...)
Definition: debug.h:111
Definition: cmd.h:292
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:1015
struct _PARSED_COMMAND * Next
Definition: cmd.h:296
#define C_OP_LOWEST
Definition: parser.c:7
static BOOL bParseError
Definition: parser.c:48
smooth NULL
Definition: ftsmooth.c:416
Definition: sacdrv.h:277
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:719
#define cmd_alloc(size)
Definition: cmddbg.h:29
static void ParseError(void)
Definition: parser.c:96
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:656

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

◆ ParseCommandPart()

static DECLSPEC_NOINLINE PARSED_COMMAND* ParseCommandPart ( REDIRECTION RedirList)
static

Definition at line 584 of file parser.c.

585 {
586  TCHAR ParsedLine[CMDLINE_LENGTH];
588  PARSED_COMMAND *(*Func)(void);
589 
590  TCHAR *Pos = _stpcpy(ParsedLine, CurrentToken) + 1;
591  DWORD_PTR TailOffset = Pos - ParsedLine;
592 
593  /* Check for special forms */
594  if ((Func = ParseFor, _tcsicmp(ParsedLine, _T("for")) == 0) ||
595  (Func = ParseIf, _tcsicmp(ParsedLine, _T("if")) == 0) ||
596  (Func = ParseRem, _tcsicmp(ParsedLine, _T("rem")) == 0))
597  {
599  /* Do special parsing only if it's not followed by /? */
600  if (_tcscmp(CurrentToken, _T("/?")) != 0)
601  {
602  if (RedirList)
603  {
604  ParseError();
605  FreeRedirection(RedirList);
606  return NULL;
607  }
608  return Func();
609  }
610  Pos = _stpcpy(Pos, _T(" /?"));
611  }
612 
613  /* Now get the tail */
614  while (1)
615  {
616  int Type = ParseToken(0, NULL);
617  if (Type == TOK_NORMAL)
618  {
619  if (Pos + _tcslen(CurrentToken) >= &ParsedLine[CMDLINE_LENGTH])
620  {
621  ParseError();
622  FreeRedirection(RedirList);
623  return NULL;
624  }
626  }
627  else if (Type == TOK_REDIRECTION)
628  {
629  if (!ParseRedirection(&RedirList))
630  return NULL;
631  }
632  else
633  {
634  break;
635  }
636  }
637  *Pos++ = _T('\0');
638 
639  Cmd = cmd_alloc(FIELD_OFFSET(PARSED_COMMAND, Command.First[Pos - ParsedLine]));
640  if (!Cmd)
641  {
642  WARN("Cannot allocate memory for Cmd!\n");
643  ParseError();
644  FreeRedirection(RedirList);
645  return NULL;
646  }
647  Cmd->Type = C_COMMAND;
648  Cmd->Next = NULL;
649  Cmd->Subcommands = NULL;
650  Cmd->Redirections = RedirList;
651  memcpy(Cmd->Command.First, ParsedLine, (Pos - ParsedLine) * sizeof(TCHAR));
652  Cmd->Command.Rest = Cmd->Command.First + TailOffset;
653  return Cmd;
654 }
Definition: cmd.h:292
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
Type
Definition: Type.h:6
#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
#define WARN(fmt,...)
Definition: debug.h:111
ush Pos
Definition: deflate.h:92
#define CMDLINE_LENGTH
Definition: help.h:12
Definition: shell.h:41
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:106
static PARSED_COMMAND * ParseFor(void)
Definition: parser.c:454
static BOOL ParseRedirection(REDIRECTION **List)
Definition: parser.c:226
LPTSTR _stpcpy(LPTSTR, LPCTSTR)
Definition: misc.c:461
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:416
static PARSED_COMMAND * ParseIf(void)
Definition: parser.c:354
char TCHAR
Definition: xmlstorage.h:189
static PARSED_COMMAND * ParseRem(void)
Definition: parser.c:576
#define _T(x)
Definition: vfdio.h:22
Definition: sacdrv.h:277
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
void(* Func)(int)
static void ParseError(void)
Definition: parser.c:96
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
VOID FreeRedirection(REDIRECTION *)
Definition: redir.c:153

Referenced by ParsePrimary().

◆ ParseError()

static void ParseError ( void  )
static

Definition at line 96 of file parser.c.

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

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

◆ ParseFor()

static PARSED_COMMAND* ParseFor ( void  )
static

Definition at line 454 of file parser.c.

455 {
458  TCHAR *Pos = List;
459 
460  Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
461  if (!Cmd)
462  {
463  WARN("Cannot allocate memory for Cmd!\n");
464  ParseError();
465  return NULL;
466  }
467  memset(Cmd, 0, sizeof(PARSED_COMMAND));
468  Cmd->Type = C_FOR;
469 
470  while (1)
471  {
472  if (_tcsicmp(CurrentToken, _T("/D")) == 0)
473  Cmd->For.Switches |= FOR_DIRS;
474  else if (_tcsicmp(CurrentToken, _T("/F")) == 0)
475  {
476  Cmd->For.Switches |= FOR_F;
477  if (!Cmd->For.Params)
478  {
480  if (CurrentToken[0] == _T('/') || CurrentToken[0] == _T('%'))
481  break;
482  Cmd->For.Params = cmd_dup(CurrentToken);
483  }
484  }
485  else if (_tcsicmp(CurrentToken, _T("/L")) == 0)
486  Cmd->For.Switches |= FOR_LOOP;
487  else if (_tcsicmp(CurrentToken, _T("/R")) == 0)
488  {
489  Cmd->For.Switches |= FOR_RECURSIVE;
490  if (!Cmd->For.Params)
491  {
493  if (CurrentToken[0] == _T('/') || CurrentToken[0] == _T('%'))
494  break;
496  Cmd->For.Params = cmd_dup(CurrentToken);
497  }
498  }
499  else
500  break;
502  }
503 
504  /* Make sure there aren't two different switches specified
505  * at the same time, unless they're /D and /R */
506  if ((Cmd->For.Switches & (Cmd->For.Switches - 1)) != 0
507  && Cmd->For.Switches != (FOR_DIRS | FOR_RECURSIVE))
508  {
509  goto error;
510  }
511 
512  /* Variable name should be % and just one other character */
513  if (CurrentToken[0] != _T('%') || _tcslen(CurrentToken) != 2)
514  goto error;
515  Cmd->For.Variable = CurrentToken[1];
516 
518  if (_tcsicmp(CurrentToken, _T("in")) != 0)
519  goto error;
520 
522  goto error;
523 
524  while (1)
525  {
526  int Type;
527 
528  /* Pretend we're inside a block so the tokenizer will stop on ')' */
529  InsideBlock++;
531  InsideBlock--;
532 
533  if (Type == TOK_END_BLOCK)
534  break;
535 
536  if (Type == TOK_END)
537  {
538  /* Skip past the \n */
539  ParseChar();
540  continue;
541  }
542 
543  if (Type != TOK_NORMAL)
544  goto error;
545 
546  if (Pos != List)
547  *Pos++ = _T(' ');
548 
550  goto error;
552  }
553  *Pos = _T('\0');
554  Cmd->For.List = cmd_dup(List);
555 
557  if (_tcsicmp(CurrentToken, _T("do")) != 0)
558  goto error;
559 
560  Cmd->Subcommands = ParseCommandOp(C_OP_LOWEST);
561  if (Cmd->Subcommands == NULL)
562  {
563  FreeCommand(Cmd);
564  return NULL;
565  }
566 
567  return Cmd;
568 
569 error:
570  FreeCommand(Cmd);
571  ParseError();
572  return NULL;
573 }
#define FOR_DIRS
Definition: cmd.h:197
Type
Definition: Type.h:6
#define _tcsicmp
Definition: xmlstorage.h:205
static TCHAR CurrentToken[CMDLINE_LENGTH]
Definition: parser.c:54
#define WARN(fmt,...)
Definition: debug.h:111
ush Pos
Definition: deflate.h:92
#define CMDLINE_LENGTH
Definition: help.h:12
Definition: parser.c:40
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:1015
static VOID StripQuotes(LPSTR in)
Definition: cmdcons.c:116
#define FOR_F
Definition: cmd.h:198
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:106
#define C_OP_LOWEST
Definition: parser.c:7
LPTSTR _stpcpy(LPTSTR, LPCTSTR)
Definition: misc.c:461
#define FOR_LOOP
Definition: cmd.h:199
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:416
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
Definition: cmd.h:292
LIST_ENTRY List
Definition: psmgr.c:57
DWORD error
Definition: parser.c:105
static TCHAR ParseChar(void)
Definition: parser.c:58
#define FOR_RECURSIVE
Definition: cmd.h:200
Definition: sacdrv.h:277
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:719
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
static void ParseError(void)
Definition: parser.c:96
#define cmd_dup(str)
Definition: cmddbg.h:32
static int InsideBlock
Definition: parser.c:56
#define memset(x, y, z)
Definition: compat.h:39

Referenced by ParseCommandPart().

◆ ParseIf()

static PARSED_COMMAND* ParseIf ( void  )
static

Definition at line 354 of file parser.c.

355 {
356  int Type;
358 
359  Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
360  if (!Cmd)
361  {
362  WARN("Cannot allocate memory for Cmd!\n");
363  ParseError();
364  return NULL;
365  }
366  memset(Cmd, 0, sizeof(PARSED_COMMAND));
367  Cmd->Type = C_IF;
368 
370  if (_tcsicmp(CurrentToken, _T("/I")) == 0)
371  {
372  Cmd->If.Flags |= IFFLAG_IGNORECASE;
374  }
375  if (_tcsicmp(CurrentToken, _T("not")) == 0)
376  {
377  Cmd->If.Flags |= IFFLAG_NEGATE;
379  }
380 
381  if (Type != TOK_NORMAL)
382  {
383  FreeCommand(Cmd);
384  ParseError();
385  return NULL;
386  }
387 
388  /* Check for unary operators */
389  for (; Cmd->If.Operator <= IF_MAX_UNARY; Cmd->If.Operator++)
390  {
391  if (_tcsicmp(CurrentToken, IfOperatorString[Cmd->If.Operator]) == 0)
392  {
394  {
395  FreeCommand(Cmd);
396  ParseError();
397  return NULL;
398  }
399  Cmd->If.RightArg = cmd_dup(CurrentToken);
400  goto condition_done;
401  }
402  }
403 
404  /* It must be a two-argument (comparison) operator. It could be ==, so
405  * the equals sign can't be treated as whitespace here. */
406  Cmd->If.LeftArg = cmd_dup(CurrentToken);
407  ParseToken(0, _T(",;"));
408 
409  /* The right argument can come immediately after == */
410  if (_tcsnicmp(CurrentToken, _T("=="), 2) == 0 && CurrentToken[2])
411  {
412  Cmd->If.RightArg = cmd_dup(&CurrentToken[2]);
413  goto condition_done;
414  }
415 
416  for (; Cmd->If.Operator <= IF_MAX_COMPARISON; Cmd->If.Operator++)
417  {
418  if (_tcsicmp(CurrentToken, IfOperatorString[Cmd->If.Operator]) == 0)
419  {
421  break;
422  Cmd->If.RightArg = cmd_dup(CurrentToken);
423  goto condition_done;
424  }
425  }
426  FreeCommand(Cmd);
427  ParseError();
428  return NULL;
429 
430 condition_done:
431  Cmd->Subcommands = ParseCommandOp(C_OP_LOWEST);
432  if (Cmd->Subcommands == NULL)
433  {
434  FreeCommand(Cmd);
435  return NULL;
436  }
437  if (_tcsicmp(CurrentToken, _T("else")) == 0)
438  {
439  Cmd->Subcommands->Next = ParseCommandOp(C_OP_LOWEST);
440  if (Cmd->Subcommands->Next == NULL)
441  {
442  FreeCommand(Cmd);
443  return NULL;
444  }
445  }
446 
447  return Cmd;
448 }
static int CurrentTokenType
Definition: parser.c:55
Type
Definition: Type.h:6
Definition: cmd.h:292
#define _tcsicmp
Definition: xmlstorage.h:205
#define IFFLAG_IGNORECASE
Definition: cmd.h:224
static TCHAR CurrentToken[CMDLINE_LENGTH]
Definition: parser.c:54
#define IF_MAX_UNARY
#define WARN(fmt,...)
Definition: debug.h:111
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:1015
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:106
#define C_OP_LOWEST
Definition: parser.c:7
#define _tcsnicmp
Definition: xmlstorage.h:207
smooth NULL
Definition: ftsmooth.c:416
#define _T(x)
Definition: vfdio.h:22
#define IFFLAG_NEGATE
Definition: cmd.h:223
static const TCHAR *const IfOperatorString[]
Definition: parser.c:13
Definition: sacdrv.h:277
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:719
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
static void ParseError(void)
Definition: parser.c:96
#define cmd_dup(str)
Definition: cmddbg.h:32
#define IF_MAX_COMPARISON
#define memset(x, y, z)
Definition: compat.h:39

Referenced by ParseCommandPart().

◆ ParsePrimary()

static PARSED_COMMAND* ParsePrimary ( void  )
static

Definition at line 656 of file parser.c.

657 {
658  REDIRECTION *RedirList = NULL;
659  int Type;
660 
661  while (IsSeparator(CurChar))
662  {
663  if (CurChar == _T('\n'))
664  return NULL;
665  ParseChar();
666  }
667 
668  if (!CurChar)
669  return NULL;
670 
671  if (CurChar == _T(':'))
672  {
673  /* "Ignore" the rest of the line.
674  * (Line continuations will still be parsed, though.) */
675  while (ParseToken(0, NULL) != TOK_END)
676  ;
677  return NULL;
678  }
679 
680  if (CurChar == _T('@'))
681  {
683  ParseChar();
684  Cmd = cmd_alloc(sizeof(PARSED_COMMAND));
685  if (!Cmd)
686  {
687  WARN("Cannot allocate memory for Cmd!\n");
688  ParseError();
689  return NULL;
690  }
691  Cmd->Type = C_QUIET;
692  Cmd->Next = NULL;
693  /* @ acts like a unary operator with low precedence,
694  * so call the top-level parser */
695  Cmd->Subcommands = ParseCommandOp(C_OP_LOWEST);
696  Cmd->Redirections = NULL;
697  return Cmd;
698  }
699 
700  /* Process leading redirections and get the head of the command */
701  while ((Type = ParseToken(_T('('), STANDARD_SEPS)) == TOK_REDIRECTION)
702  {
703  if (!ParseRedirection(&RedirList))
704  return NULL;
705  }
706 
707  if (Type == TOK_NORMAL)
708  return ParseCommandPart(RedirList);
709  else if (Type == TOK_BEGIN_BLOCK)
710  return ParseBlock(RedirList);
711  else if (Type == TOK_END_BLOCK && !RedirList)
712  return NULL;
713 
714  ParseError();
715  FreeRedirection(RedirList);
716  return NULL;
717 }
static DECLSPEC_NOINLINE PARSED_COMMAND * ParseCommandPart(REDIRECTION *RedirList)
Definition: parser.c:584
Type
Definition: Type.h:6
#define WARN(fmt,...)
Definition: debug.h:111
static PARSED_COMMAND * ParseBlock(REDIRECTION *RedirList)
Definition: parser.c:298
Definition: parser.c:40
static BOOL IsSeparator(TCHAR Char)
Definition: parser.c:33
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:106
#define C_OP_LOWEST
Definition: parser.c:7
static BOOL ParseRedirection(REDIRECTION **List)
Definition: parser.c:226
smooth NULL
Definition: ftsmooth.c:416
#define _T(x)
Definition: vfdio.h:22
static TCHAR ParseChar(void)
Definition: parser.c:58
Definition: sacdrv.h:277
static PARSED_COMMAND * ParseCommandOp(int OpType)
Definition: parser.c:719
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
static TCHAR CurChar
Definition: parser.c:52
static void ParseError(void)
Definition: parser.c:96
VOID FreeRedirection(REDIRECTION *)
Definition: redir.c:153
Definition: cmd.h:292

Referenced by ParseCommandOp().

◆ ParseRedirection()

static BOOL ParseRedirection ( REDIRECTION **  List)
static

Definition at line 226 of file parser.c.

227 {
228  TCHAR *Tok = CurrentToken;
229  BYTE Number;
230  REDIR_MODE RedirMode;
231  REDIRECTION *Redir;
232 
233  if (*Tok >= _T('0') && *Tok <= _T('9'))
234  Number = *Tok++ - _T('0');
235  else
236  Number = *Tok == _T('<') ? 0 : 1;
237 
238  if (*Tok++ == _T('<'))
239  {
240  RedirMode = REDIR_READ;
241  if (*Tok == _T('<'))
242  goto fail;
243  }
244  else
245  {
246  RedirMode = REDIR_WRITE;
247  if (*Tok == _T('>'))
248  {
249  RedirMode = REDIR_APPEND;
250  Tok++;
251  }
252  }
253 
254  if (!*Tok)
255  {
256  /* The file name was not part of this token, so it'll be the next one */
258  goto fail;
259  Tok = CurrentToken;
260  }
261 
262  /* If a redirection for this handle number already exists, delete it */
263  while ((Redir = *List))
264  {
265  if (Redir->Number == Number)
266  {
267  *List = Redir->Next;
268  cmd_free(Redir);
269  continue;
270  }
271  List = &Redir->Next;
272  }
273 
274  Redir = cmd_alloc(FIELD_OFFSET(REDIRECTION, Filename[_tcslen(Tok) + 1]));
275  if (!Redir)
276  {
277  WARN("Cannot allocate memory for Redir!\n");
278  goto fail;
279  }
280  Redir->Next = NULL;
282  Redir->Number = Number;
283  Redir->Mode = RedirMode;
284  _tcscpy(Redir->Filename, Tok);
285  *List = Redir;
286  return TRUE;
287 
288 fail:
289  ParseError();
291  *List = NULL;
292  return FALSE;
293 }
#define TRUE
Definition: types.h:120
enum _REDIR_MODE REDIR_MODE
static TCHAR CurrentToken[CMDLINE_LENGTH]
Definition: parser.c:54
#define WARN(fmt,...)
Definition: debug.h:111
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
_TCHAR * _tcscpy(_TCHAR *to, const _TCHAR *from)
Definition: tcscpy.h:8
static int ParseToken(TCHAR ExtraEnd, TCHAR *Separators)
Definition: parser.c:106
IN PVCB IN PBCB OUT PDIRENT IN USHORT IN POEM_STRING Filename
Definition: fatprocs.h:925
REDIR_MODE Mode
Definition: cmd.h:351
HANDLE OldHandle
Definition: cmd.h:349
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:416
BYTE Number
Definition: cmd.h:350
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
LIST_ENTRY List
Definition: psmgr.c:57
TCHAR Filename[]
Definition: cmd.h:352
unsigned char BYTE
Definition: mem.h:68
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
#define STANDARD_SEPS
Definition: parser.c:31
#define cmd_alloc(size)
Definition: cmddbg.h:29
#define cmd_free(ptr)
Definition: cmddbg.h:31
static void ParseError(void)
Definition: parser.c:96
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
VOID FreeRedirection(REDIRECTION *)
Definition: redir.c:153
struct _REDIRECTION * Next
Definition: cmd.h:348

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

◆ ParseRem()

static PARSED_COMMAND* ParseRem ( void  )
static

Definition at line 576 of file parser.c.

577 {
578  /* Just ignore the rest of the line */
579  while (CurChar && CurChar != _T('\n'))
580  ParseChar();
581  return NULL;
582 }
smooth NULL
Definition: ftsmooth.c:416
#define _T(x)
Definition: vfdio.h:22
static TCHAR ParseChar(void)
Definition: parser.c:58
static TCHAR CurChar
Definition: parser.c:52

Referenced by ParseCommandPart().

◆ ParseToken()

static int ParseToken ( TCHAR  ExtraEnd,
TCHAR Separators 
)
static

Definition at line 106 of file parser.c.

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

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

◆ Unparse()

TCHAR* Unparse ( PARSED_COMMAND Cmd,
TCHAR Out,
TCHAR OutEnd 
)

Definition at line 905 of file parser.c.

906 {
907  TCHAR Buf[CMDLINE_LENGTH];
908  PARSED_COMMAND *Sub;
909  REDIRECTION *Redir;
910 
911 /*
912  * Since this function has the annoying requirement that it must avoid
913  * overflowing the supplied buffer, define some helper macros to make
914  * this less painful.
915  */
916 #define CHAR(Char) \
917 do { \
918  if (Out == OutEnd) return NULL; \
919  *Out++ = Char; \
920 } while (0)
921 #define STRING(String) \
922 do { \
923  if (Out + _tcslen(String) > OutEnd) return NULL; \
924  Out = _stpcpy(Out, String); \
925 } while (0)
926 #define PRINTF(Format, ...) \
927 do { \
928  UINT Len = _sntprintf(Out, OutEnd - Out, Format, __VA_ARGS__); \
929  if (Len > (UINT)(OutEnd - Out)) return NULL; \
930  Out += Len; \
931 } while (0)
932 #define RECURSE(Subcommand) \
933 do { \
934  Out = Unparse(Subcommand, Out, OutEnd); \
935  if (!Out) return NULL; \
936 } while (0)
937 
938  switch (Cmd->Type)
939  {
940  case C_COMMAND:
941  /* This is fragile since there could be special characters, but
942  * Windows doesn't bother escaping them, so for compatibility
943  * we probably shouldn't do it either */
944  if (!SubstituteForVars(Cmd->Command.First, Buf)) return NULL;
945  STRING(Buf);
946  if (!SubstituteForVars(Cmd->Command.Rest, Buf)) return NULL;
947  STRING(Buf);
948  break;
949  case C_QUIET:
950  CHAR(_T('@'));
951  RECURSE(Cmd->Subcommands);
952  break;
953  case C_BLOCK:
954  CHAR(_T('('));
955  for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
956  {
957  RECURSE(Sub);
958  if (Sub->Next)
959  CHAR(_T('&'));
960  }
961  CHAR(_T(')'));
962  break;
963  case C_MULTI:
964  case C_IFFAILURE:
965  case C_IFSUCCESS:
966  case C_PIPE:
967  Sub = Cmd->Subcommands;
968  RECURSE(Sub);
969  PRINTF(_T(" %s "), OpString[Cmd->Type - C_OP_LOWEST]);
970  RECURSE(Sub->Next);
971  break;
972  case C_IF:
973  STRING(_T("if"));
974  if (Cmd->If.Flags & IFFLAG_IGNORECASE)
975  STRING(_T(" /I"));
976  if (Cmd->If.Flags & IFFLAG_NEGATE)
977  STRING(_T(" not"));
978  if (Cmd->If.LeftArg && SubstituteForVars(Cmd->If.LeftArg, Buf))
979  PRINTF(_T(" %s"), Buf);
980  PRINTF(_T(" %s"), IfOperatorString[Cmd->If.Operator]);
981  if (!SubstituteForVars(Cmd->If.RightArg, Buf)) return NULL;
982  PRINTF(_T(" %s "), Buf);
983  Sub = Cmd->Subcommands;
984  RECURSE(Sub);
985  if (Sub->Next)
986  {
987  STRING(_T(" else "));
988  RECURSE(Sub->Next);
989  }
990  break;
991  case C_FOR:
992  STRING(_T("for"));
993  if (Cmd->For.Switches & FOR_DIRS) STRING(_T(" /D"));
994  if (Cmd->For.Switches & FOR_F) STRING(_T(" /F"));
995  if (Cmd->For.Switches & FOR_LOOP) STRING(_T(" /L"));
996  if (Cmd->For.Switches & FOR_RECURSIVE) STRING(_T(" /R"));
997  if (Cmd->For.Params)
998  PRINTF(_T(" %s"), Cmd->For.Params);
999  PRINTF(_T(" %%%c in (%s) do "), Cmd->For.Variable, Cmd->For.List);
1000  RECURSE(Cmd->Subcommands);
1001  break;
1002  }
1003 
1004  for (Redir = Cmd->Redirections; Redir; Redir = Redir->Next)
1005  {
1006  if (!SubstituteForVars(Redir->Filename, Buf))
1007  return NULL;
1008  PRINTF(_T(" %c%s%s"), _T('0') + Redir->Number,
1009  RedirString[Redir->Mode], Buf);
1010  }
1011  return Out;
1012 }
#define FOR_DIRS
Definition: cmd.h:197
Definition: cmd.h:292
Definition: cmd.h:292
#define RECURSE(Subcommand)
Definition: cmd.h:292
#define IFFLAG_IGNORECASE
Definition: cmd.h:224
#define CMDLINE_LENGTH
Definition: help.h:12
Definition: cmd.h:292
#define FOR_F
Definition: cmd.h:198
struct _PARSED_COMMAND * Next
Definition: cmd.h:296
#define C_OP_LOWEST
Definition: parser.c:7
REDIR_MODE Mode
Definition: cmd.h:351
#define PRINTF(Format,...)
#define FOR_LOOP
Definition: cmd.h:199
smooth NULL
Definition: ftsmooth.c:416
BYTE Number
Definition: cmd.h:350
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
Definition: cmd.h:292
#define IFFLAG_NEGATE
Definition: cmd.h:223
TCHAR Filename[]
Definition: cmd.h:352
static const TCHAR *const IfOperatorString[]
Definition: parser.c:13
#define STRING(String)
#define FOR_RECURSIVE
Definition: cmd.h:200
static const TCHAR RedirString[][3]
Definition: parser.c:11
Definition: sacdrv.h:277
Definition: cmd.h:292
BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest)
Definition: cmd.c:1372
static const TCHAR OpString[][3]
Definition: parser.c:9
struct _REDIRECTION * Next
Definition: cmd.h:348
Definition: cmd.h:292
#define CHAR(Char)

Referenced by ExecuteAsync().

Variable Documentation

◆ bLineContinuations

BOOL bLineContinuations
static

Definition at line 49 of file parser.c.

Referenced by ParseChar(), and ParseCommand().

◆ bParseError

BOOL bParseError
static

Definition at line 48 of file parser.c.

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

◆ CurChar

◆ CurrentToken

TCHAR CurrentToken[CMDLINE_LENGTH]
static

◆ CurrentTokenType

int CurrentTokenType
static

Definition at line 55 of file parser.c.

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

◆ IfOperatorString

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: vfdio.h:22

Definition at line 13 of file parser.c.

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

◆ InsideBlock

int InsideBlock
static

Definition at line 56 of file parser.c.

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

◆ OpString

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

Definition at line 9 of file parser.c.

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

◆ ParseLine

TCHAR ParseLine[CMDLINE_LENGTH]
static

Definition at line 50 of file parser.c.

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

◆ ParsePos

TCHAR* ParsePos
static

Definition at line 51 of file parser.c.

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

◆ RedirString

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

Definition at line 11 of file parser.c.

Referenced by EchoCommand(), and Unparse().