Skip to content

Latest commit

 

History

History
1828 lines (1706 loc) · 57.8 KB

PARSING.md

File metadata and controls

1828 lines (1706 loc) · 57.8 KB

Overview of fvwm2 parsing as of 16-Aug-2014

Sources of input to parse

  • Configuration files and files read with the Read command

    • May be preprocessed by FvwmCpp or FvwmM4
  • Input from the PipeRead command

  • Input from modules to fvwm through the module pipes

    • Fixed or generated strings from modules (e.g. FvwmPager, FvwmButtons etc.)

    • User input, e.g. from FvwmConsole or FvwmCommand.

  • Module input from fvwm through the module pipes is parsed by the receiving module.

    • Binary input in predefined packets is only partially parsed (packet type). The format and meaning of the packets is a property of the module protocol.

    • The payload of some string packets (e.g. generated by the SendToModule command) is a free form string that is interpreted by the receiving module. The module does any necessary parsing. Example:

      SendToModule FvwmButtons changebutton 0 title foo, activetitle bar

  • Commands generated internally by fvwm as the result of an external event, for example, an Ewmh message. This is used quite often; instead of calling the function to maximize a window directly, one may generate a command string that is passed to execute_function(). Examples are virtual.c:CMD_EdgeResistance() or ewmh_events.c:ewmh_DesktopGeometry().

Various properties of parser input and the communication channels

  • Maximum length of of lines read from a file is hard coded ro 1024 bytes in read.c:run_command_stream(). This is applicable to configuration files and the Read and Piperead commands.

  • The maximum depth of nested files opened through the Read command is hard coded to 40 (read.c).

  • Input from files or the PipeRead command may have an unlimited number of lines.

  • The maximum length of packets that can be sent in one chunk from fvwm to the modules or back is hard coded to 256 including the packet header (FvwmPacketMaxSize in libs/Module.h). This is an artifact of module communication through pipes. 256 bytes is the size that all systems guarantee to be sent through the pipe in an atomic block.

    Anything larger than that may be split into multiple write calls, leading to mutilated messages in either direction. Packets from fvwm to the modules are simply truncated to 256 bytes (module_interface.c:make_vpacket()). Packets from the modules to fvwm are possibly sent in multiple pieces (write call in Module.c:SendText()). Fvwm can theoretically handle any size of module input (module_list.c:module_receive()).

  • Input from modules to fvwm is pre-parsed in module_interface.c:module_input_execute(), i.e. fvwm checks whether the command name of the packet is "popup" and does some special processing if that is the case (this command name is not to be confused with the command from the text to be executed by fvwm; its a fixed field in the packet). This is done before any regular processing of the input.

  • Input from the modules is not executed right away but stored in a queue and executed when fvwm can process it (this is important because otherwise module input might interfere with function execution) (module_interface.c:ExecuteCommandQueue()).

Fvwm's central parsing function: execute_function()

  • All input to the parser is passed through functions.c:__execute_command_line().

    NOTE: This function is called __execute_function() in fvwm.

  • __execute_command_line is called from two places:

    • execute_function() is just a wrapper exported rom functions.c. There are two more wrappers, execute_function_override_wcontext() and execute_function_override_window() which change the execution context of the command (see below) and then call execute_function().

    • __run_complex_function_items() calls __execute_command_line() to process the individual commands of a complex function. In other words: The items of a complex function are passed twice through the parser. First when the complex function is defined, and a second time when they are executed (they are treated differently in both passes, see further down).

  • The call to __execute_command_line() is passed various pieces of information:

    
       void __execute_command_line(
     cond_rc_t *cond_rc,
         const exec_context_t *exc,
         char *action,
     FUNC_FLAGS_TYPE exec_flags,
         char *args[],
         Bool has_ref_window_moved)
    
    • cond_rc is a pointer to memory where the return code of command line execution is to be stored. This can be used in scripting through complex functions (__run_complex_function_items()) and by the internal caller of execute_function. It is also one of the parameters of the CMD_... functions, and it's important that cond_rc is passed around and not set to a NULL pointer except by the first call triggering command line processing.

    • exc is the execution context of the command line (execcontext.h). This is a vital data structure for command line processing and execution. It contains information about the originator of the command and the assiciated application (type (module, event, scheduler, ...), the actual X event, the module, the window). This data is used during command execution, e.g. to identify the window on which a command is executed or to determine the pointer position; some commands work differently when input comes from the mouse or the keyboard. It is also used during variable expansion (e.g. to expand window related extended parameters like $[w.id]).

      It is important to properly set the execution context whenever a command line is generated. Currently, some of the Ewmh code fails to do so for historical reasons which I won't explain here. This needs to be fixed eventually.

    • action is the command line to parse and execute.

    • exec_flags are flags that affect command parsing and execution that may become necessary in some contexts not related to the originator of the command. The flags are defined in the structure execute_flags_t in functions.h.

      • FUNC_NEEDS_WINDOW commands that need a context window are not executed if it's missing.
      • FUNC_DONT_REPEAT the command line is not repeatable (see CMD_Repeat).
      • FUNC_ADD_TO signals that the command is the addtofunc or + command.
      • FUNC_DECOR signals that the command is a decor related command.
      • FUNC_ALLOW_UNMANAGED allows running a command with an overrideredirect window.
      • FUNC_IS_UNMANAGED signals that the context window is an overrideredirect window.
      • FUNC_DONT_EXPAND_COMMAND suppresses expansion of variables on the command line.
      • FUNC_DONT_DEFER suppresses deferring execution of commands that need a target window (normally these are put into the queue and processed later).
    • args is the array of the positional arguments during complex function execution. For calls from execute_function() it's a NULL pointer.

    • has_ref_window_moved is a separate flag (hack) that triggers some special treatment of the execution of the command Move, Resize and AnimatedMove (but forgets the ResizeMove and ResizeMoveMaximize commands). This should ratehr be stored in exec_flags.

Command line parsing

The command independent parsing of any command line is done by the __execute_command_line() call. The parsing procedure is as follows. Remember that action is the command line to be parsed. The pointer and the memory it points to are updated during the parsing process.

  • Step 1 Handle NULL pointer, whitespace and comments

    1. Stop parsing and execute nothing if action is a NULL pointer. DONE
    2. Strip all whitespace from the beginning of the command line.
    3. Stop parsing and execute nothing if action is a NULL pointer or an empty string. (Note that some of the functions in libs/Parse.c never return an empty string but rather a NULL pointer. Parsing in the individual commands often relies on that.) DONE
    4. If the first character is '#', is a comment. Stop parsing and execute nothing. DONE
  • Step 2

    1. Increment the nested function depth.
    2. If the function depth is too high, print an error message and stop. DONE
    3. Determine the context window.
  • Step 3 Handle prefixes

    1. If action begins with -, set the FUNC_DONT_EXPAND_COMMAND flag and skip the - character.
    2. Peek the first token of action.
    3. If the token is silent, set the global Scr.flags.are_functions_silent if not already set, strip the token from action and go back to (b).
    4. If the token is keeprc, set the internal do_keep_rc flag, strip the token from action and go back to (b). (A dummy return code variable is used in the command execution.)
  • Step 4 Finish if there is no remaining action to execute.

  • Step 5 Parse the command token

    1. Get (but not strip) the command token from the action.

    2. Expand variables in the token (expand.c:expand_vars()).

    3. If the token does not start with a '*':

      • strip all characters from and including the first whitespace from the command token.

        [Bug: Complex function names cannot have embedded whitespace because of this, see comment in the code.]

        [Note: If a command line begins with

        *foo

        (including the double quotes), the double quotes are removed by GetNextToken, and the remaining token does begin with *.]

      • find the internal command matching this token from the builtin function table. Note that any token beginning with + or + is treated as the + command.

      [What the heck is this good for?]

  • Step 6

    If a we're currently adding to a decor, and the command token designates a builtin function that does not have the FUNC_DECOR flag set, generate a warning that the command cannot be added to the decor.

  • Step 7

    If the FUNC_DONT_EXPAND_COMMAND flag is not set, expand variables in the action, including the part from which the command token was extracted above. (The ismod flag of the call to expand_vars() flag is set if the action begins with '*').

    [Note: The command token was parsed before expansion in step 5. Now the whole line including the token is expanded before further processing. This may or may not cause subtle bugs with quoting and expansion.]

  • Step 8

    If the expanded action begins with '*' treat it as a module configuration line. GOTO step 10

    [BUG: Contrary to step 5 (c), a line beginning with

    *foo

    is not recognized as a module configuration line because it begins with double quotes, not *.]

  • Step 9

    Execute the action

    1. Prepare the execution context.

    2. If it's a builtin function other than Function, strip the first token from the expanded action and defer or execute the CMD_() function as necessary with the proper execution context. GOTO step 10

    3. If it's the builtin command Function, strip the first token from the expanded action.

      [Note: this may again be a different substring than in step 5 (c) or step 8.]

    4. Call execute_complex_function with the remaining expanded action.

    5. If no complex function with that name can be found and it was not the builtin command Function, assume that the builtin command was Module and try to execute CMD_Module with the remaining expanded action as its arguments.

  • Step 10 Cleanup

    1. Clear the Scr.flags.are_functions_silent flag if set in step 3 (c).
    2. Store the number of pending breaks from the functions return code structure in the original cond_rc (which may be a different one in case the command was prefixed with keeprc).
    3. Decrement the nested function depth.

Tokenization

The token parsing code is in libs/Parse.c:DoPeekToken() and CopyToken() (called by the former). DoPeekToken takes the input string, a pointer to memory where it stores the pointer to the resulting token, a pointer to memory to store the output string (buffer with hardcoded length MAX_TOKEN_LENGTH = 1023 bytes (libs/Parse.h), and may be provided a string of additional characters to be treated as spaces, a string of input token delimiter characters, and a pointer where the character that ended the token is stored (output delimiter). By default, the set of space characters contains the character class determined by isspace(), and the set of input delimiter characters is empty

  • Step 1 (DoPeekToken)

    1. Strip all space characters (see above) from the beginning of the input string.
    2. Call CopyToken() with the remaining string.
  • Step 2 (CopyToken)

    1. Set the src pointer to the beginning of the input string. The dest pointer is passed in as a function argument.
    2. If src is at the end of the string, GOTO stp 3
    3. If *src is a space character or an input delimiter, GOTO stp 3
    4. If *src is a quote character (either a double quote chararcter, a single quote or a backtick), GOTO step 2A
    5. Otherwise, GOTO step 2B
  • Step 2A

    1. c := *src
    2. Skip over the src quote character (src++)
    3. If *src is c or the end of string, GOTO (f)
    4. If *src is a backslash and the next character is not the end of the input string (null byte), skip over the backslash in the input (src++).
    5. If there's still room in the output string, copy *src to *dest and increment both pointers, otherwise just skip over the input character (src++). GOTO (c)
    6. If *src is c, skip over it (src++). GOTO step 2 (b)
  • Step 2B

    1. If *src is a backslash and the next character is not the end of the input string (null byte), skip over the backslash in the input (src++).
    2. If there's still room in the output string, copy *src to *dest and increment both pointers, otherwise just skip over the input character (src++). GOTO step 2 (b)
  • Step 3

    1. Set the output delimiter to the character pointer to by src (i.e. the first character after the token).
    2. Terminate the destination string with a null byte.
    3. If src points to a string of zero or more spaces followed by an input delimiter, store the delimiter as the output delimiter and return a pointer to the character after that.
    4. Otherwise, if src is not at the end of the string, return the character after src.
    5. Otherwise src points to the end of the string; return src.

Step 4 (DoPeekToken)

  1. If the remaining string has the length zero, set the token pointer to NULL.
  2. Return a pointer to the beginning of the next token in the input string. DONE

Variable expansion

Variable expansion is done expand.c:expand_vars(). The function takes an input string, the execution context, cond_rc and an array of positional parameters and returns the string with the variables expanded. It also takes the flags addto (never set) and ismod (set in step 7 of the parsing algorithm if the command begins with *).

[BUG: The addto flag is actually never set when the function is called but instead used as a bogus local variable.]

  • Step 1

    1. l := length of input
    2. If the input begins with '*', set the addto flag.
    3. Calculate the length of the expanded string and allocate memory for it.
  • Step 2 (Scan for variables)

    1. Begin at the start of the input and output strings.

    2. Copy all character up to but excluding the next '$' character to the output string (stop at the end of string).

    3. If we're at the end of the string, stop. DONE

    4. Otherwise we're now at a $ character. If the ismod flag set and the next character is a letter, copy both to the output string. GOTO (b)

      [Note: In module configuration lines, variable in the form $<letter> are not expanded. There are probably several bugs because of this logic.]

  • Step 3 (Expand a variable)

    1. If the next character is a $, copy one $ to the output, skip over two $ in the input and GOTO step 2 (b)
    2. If the next character is '[', GOTO step 4
    3. If the $<character> sequence does not designate a valid one character variable, copy it to the output and GOTO step 2 (b)
    4. Otherwise, skip over the $ and the next character in the input and copy the value of the one character variable to the output. GOTO step 2 (b)
  • Step 4 (Expand an extended variable)

    1. If addto is set, copy the $[ to the output and GOTO step 2 (b)
    2. Determine the name of the extended variable. The name starts after the initial [ character and ends before the final ] character. The final ] character is the first occurence of the character ] after the $, where the number of [ minus the number of ] is zero (i.e., square brackets can be nested). If the end of string is encountered, just copy everything to the output and GOTO step 2 (b)
    3. Otherwise, if the variable name contains at least one $, call expand vars with the name to expand nested variable references. The result of this expansion is taken as the new variable name.
    4. If an extended variable with that name exists, copy its value into the output, skip the $[...] in the input and GOTO step 2 (b)
    5. Otherwise copy the "$[...]" to the output and GOTO step 2 (b)

The second level of parsing

When __execute_command_line() has finished its work it either tries to execute a module, a builtin command or a complex function (or nothing at all and just returns). Module execution is treated like a call of CMD_Module(), so there are two different ways how parsing continues. A third context of parsing is, when a module receives a packet from fvwm.

  • Parsing of builtin commands is done individually by the CMD_<builtin>() functions.

  • Parsing and of a complex function call and its items is handled by the function functions.c:execute_complex_function().

  • Parsing of module configuration lines is done by the modules with help from libs/Modules.c. There is also an optional step of module variable expansion that is implemented in Modules.c:module_expand_action(). It replaces some module variables in the string that is going to be sent to fvwm, e.g. $width or $x. FvwmButtons, FvwmIconMan and FvwmTaskBar and use this mechanism.

Parsing of complex function calls

Implemented in functions.c:execute_complex_function().

  • Step 1

    1. Peek the first token of the action.
    2. Look it up in the list of complex functions.
    3. If no such function exists, return an error. DONE
    4. Split the action into tokens using GetNextToken. Store the original action (without the function name) followed by the first ten tokens in the positional arguments array.
    5. Set up an execution context for the function items.
    6. Call __run_complex_function_items().
  • Step 2 (__run_complex_function_items())

    1. For each complec function iten, call __execute_command_line() with the FUNC_DONT_DEFER flag and the list of positional arguments. This causes the function item command text to be passed through the parser again. DONE

Parsing needs of the builtin commands

Note: Let's attempt to formulate the existing syntax in ABNF (rfc5234).

Definitions that need defining for the below

  • FLAG = !!!;
  • DECOR = !!!;
  • FONTNAME = !!!;
  • IMAGEFILE = !!!;
  • GRADIENT = !!!;
  • MOVEARGS = !!!;
  • MODULECONFIG = !!!;
  • CONDITION = !!!;
  • COLOUR_FG = !!!;
  • COLOUR_BG = !!!;
  • COMMAND = !!!; (builtin; can also be one of FUNCNAME)
  • FUNCNAME = !!!; (StartFunction | ExitFunction | etc, plus user-defined)
  • SHELL = !!!;
  • KEYNAME = !!!;
  • STYLEOPTION = !!!; (massive list of style options!!!)
  • TOKEN = !!! ; Same as string?
  • STRING = !!! ; Sequence of characters?
  • RESTOFLINE = !!! ; STRING?
  • RESTOFLINE_COMMAND = !!! ; COMMAND

Types

WSC = %x20 / %x09
WS = *WSC
DIGIT = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
SIGNPOS = "+"
SIGNNEG = "-"
SIGN = SIGNPOS / SIGNNEG
POSINT = [SIGNPOS] 1*DIGIT
INT = [SIGN] 1*DIGIT
INTPERCENTAGE = 1DIGIT | 2DIGIT | ("0" / "1") 2DIGIT
TRUE = "yes" / "y" / "1" / "t" / "true"
FALSE = "no" / "n" / "0" / "f" / "false"
BOOL = TRUE / FALSE
TOGGLE = "toggle"
BOOL_OR_TOGGLE = BOOL / TOGGLE
MODIFIERS = "s" / "c" / "l" / "m" / "1" / "2" / "3" / "4" / "5" / "a"
BINDINGMODIFIERS = "n" / 1*MODIFIERS
PATH = ["/"] *(STRING "/") [STRING]
VISIBLE_NAME = !!!
CLASS = !!!
RESOURCE = !!!
NAME = !!!
WINDOW_ID = !!!
WINDOWSELECTOR = VISIBLE_NAME / CLASS / RESOURCE / NAME / WINDOW_ID
BINDINGCONTEXT = "R" / "W" / "D" / "T" / "F" / "A" / "S" / "M" / "I"
BINDINGCONTEXT = "[" / "]" / "-" / "_"
BINDINGCONTEXT = "<" / "^" / ">" / "v"
BINDINGCONTEXT = DIGIT
MODULENAME = "MvwmAnimate" / "MvwmButtons" / ; etc...
MODULALIAS = TOKEN
TOKEN_DECORNAME = TOKEN
FUNCNAME = TOKEN
MENUNAME = TOKEN
MENUSTYLENAME = TOKEN
STYLENAME = TOKEN / "*"
DIRS_MAIN = "North" / "N"
DIRS_MAIN =/ "East" / "E"
DIRS_MAIN =/ "South" / "S"
DIRS_MAIN =/ "West" / "W"
DIRS_DIAG = DIRS_MAIN
DIRS_DIAG =/ "NorthEast" / "NW"
DIRS_DIAG =/ "SouthEast" / "SE"
DIRS_DIAG =/ "SouthWest" / "SW"
DIRS_DIAG =/ "NorthWest" / "NW"
DIRS_CENTER = DIRS_DIAG / "Center" / "C"
COLORSET_NUM = POSINT
BUTTON = 1*DIGIT
VERSION = POSINT "." POSINT "." POSINT

Commands

CMD_ADDBUTTONSTYLE = "AddButtonStyle"
	ADDBUTTONSTYLEBUTTON [ADDBUTTONSTYLESTATE]
	[ADDBUTTONSTYLESTYLE] [ADDBUTTONSTYLEFLAG]
ADDBUTTONSTYLEBUTTON = POSINT ("All" / "Left" / "Right")
ADDBUTTONSTYLESTATE = "ActiveUp"
ADDBUTTONSTYLESTATE =/ "ActiveDown"
ADDBUTTONSTYLESTATE =/ "InactiveUp"
ADDBUTTONSTYLESTATE =/ "InactiveDown"
ADDBUTTONSTYLESTATE =/ ADDBUTTONSTYLEACTIVE
ADDBUTTONSTYLESTATE =/ "Inactive"
ADDBUTTONSTYLESTATE =/ TOGGLE
ADDBUTTONSTYLESTATE =/ "AllActive"
ADDBUTTONSTYLESTATE =/ "AllInactive"
ADDBUTTONSTYLESTATE =/ "AllNormal"
ADDBUTTONSTYLESTATE =/ "AllToggled"
ADDBUTTONSTYLESTATE =/ "AllUp"
ADDBUTTONSTYLESTATE =/ "AllDown"
ADDBUTTONSTYLESTATE =/ "AllActiveUp"
ADDBUTTONSTYLESTATE =/ "AllActiveDown"
ADDBUTTONSTYLESTATE =/ "AllInactiveUp"
ADDBUTTONSTYLESTATE =/ "AllInactiveDown"
ADDBUTTONSTYLEACTIVE = "Active" - implies FOCUSED_WINDOW
ADDBUTTONSTYLEFLAG = ["!"]ADDBUTTONSTYLEKEYWORD *("," ["!"]ADDBUTTONSTYLEKEYWORD)
ADDBUTTONSTYLEKEYWORD = 1*("UseTitleStyle" / "UseBorderStyle") *("Raised" / "Sunk" / "Flat")

CMD_ADDTITLESTYLE = "AddTitleStyle" [ADDTITLESTYLESTATE]
	[ADDTITLESTYLESTYLE] [ADDTITLESTYLEFLAG]
ADDTITLESTYLESTATE = "ActiveUp"
ADDTITLESTYLESTATE =/ "ActiveDown"
ADDTITLESTYLESTATE =/ "InactiveUp"
ADDTITLESTYLESTATE =/ "InactiveDown"
ADDTITLESTYLESTATE =/ ADDTITLESTYLEACTIVE
ADDTITLESTYLESTATE =/ "Inactive"
ADDTITLESTYLESTATE =/ "toggled"
ADDTITLESTYLESTATE =/ "AllActive"
ADDTITLESTYLESTATE =/ "AllInactive"
ADDTITLESTYLEFLAG = ["!"] ADDTITLESTYLEFLAGKEYWORD *("," ["!"] ADDTITLESTYLEFLAGKEYWORD)
ADDTITLESTYLEACTIVE = "Active" ; - implies FOCUSED_WINDOW
; (XXX = TitleStyle/ButtonStyle relationships here...)
CMD_ADDTOFUNC = "AddToFunc" FUNCNAME ADDTOFUNCFUNCDEFS RESTOFLINE_COMMAND
ADDTOFUNCFUNCDEFS = "I"
ADDTOFUNCFUNCDEFS =/ "M"
ADDTOFUNCFUNCDEFS =/ "C"
ADDTOFUNCFUNCDEFS =/ "H"
ADDTOFUNCFUNCDEFS =/ "D"
CMD_ADDTOMENU = "AddToMenu" MENUNAME [ADDTOMENULABEL RESTOFLINE_COMMAND]
ADDTOMENULABEL = STRING
CMD_ANIMATEDMOVE = "AnimatedMove" ANIMATEMOVEARGS ANIMATEMOVEARGS
	[ANIMATEDMOVEKEYWORD]
ANIMATEMOVEARGS = !!!
ANIMATEDMOVEKEYWORD = "Warp"
CMD_ASTERISK = "Asterisk" [MODULE_LINE]
CMD_BEEP = "Beep"
CMD_BORDERSTYLE = "BorderStyle" BORDERSTYLESTATE
	[BORDERSTYLESTYLE] [BORDERSTYLEFLAG]
BORDERSTYLESTATE = "Active" / "Inactive"
BORDERSTYLESTYLE = "TiledPixmap" / "Colorset"
BORDERSTYLEFLAG = ["!"] BORDERSTYLEKEYWORD ("," ["!"] BORDERSTYLEKEYWORD)
BORDERSTYLEKEYWORD = "HiddenHandles"
BORDERSTYLEKEYWORD =/ "NoInset"
BORDERSTYLEKEYWORD =/ "Raised"
BORDERSTYLEKEYWORD =/ "Sunk"
BORDERSTYLEKEYWORD =/ "Flat"
BORDERSTYLEKEYWORD =/ "Simple"
CMD_BUGOPTS = "BugOpts" BUGOPTSOPTION
BUGOPTSOPTION = 1*(BUGOPTSKEYWORD [BOOL_OR_TOGGLE])
BUGOPTSKEYWORD = "FlickingMoveWorkaround"
BUGOPTSKEYWORD =/ "MixedVisualWorkaround"
BUGOPTSKEYWORD =/ "ModalityIsEvil"
BUGOPTSKEYWORD =/ "RaiseOverNativeWindows"
BUGOPTSKEYWORD =/ "RaiseOverUnmanaged"
BUGOPTSKEYWORD =/ "FlickingQtDialogsWorkaround"
BUGOPTSKEYWORD =/ "QtDragnDropWorkaround"
BUGOPTSKEYWORD =/ "EWMHIconicStateWorkaround"
BUGOPTSKEYWORD =/ "DisplayNewWindowNames"
BUGOPTSKEYWORD =/ "ExplainWindowPlacement"
BUGOPTSKEYWORD =/ "DebugCRMotionMethod"
BUGOPTSKEYWORD =/ "TransliterateUtf8"
CMD_BUSYCURSOR = "BusyCursor" BUSYCURSOROPTION *("," BUSYCURSOROPTION)
BUSYCURSOROPTION = 1*(BUSYCURSORKEYWORD BOOL)
BUSYCURSORKEYWORD = "DynamicMenu"
BUSYCURSORKEYWORD =/ "ModuleSynchronous"
BUSYCURSORKEYWORD =/ "Read"
BUSYCURSORKEYWORD =/ "Wait"
BUSYCURSORKEYWORD =/ "*"
CMD_BUTTONSTATE = "ButtonState" BUTTONSTATEOPTION *("," BUTTONSTATEOPTION)
BUTTONSTATEOPTION = BUTTONSTATEKEYWORD [BOOL]
BUTTONSTATEKEYWORD = "ActiveUp"
BUTTONSTATEKEYWORD =/ "ActiveDown"
BUTTONSTATEKEYWORD =/ "InactiveUp"
BUTTONSTATEKEYWORD =/ "InactiveDown"
CMD_BUTTONSTYLE = "ButtonStyle" BUTTONSTYLEBUTTON
	[BUTTONSTYLESTATE] [BUTTONSTYLESTYLE] [FLAGS]
BUTTONSTYLEBUTTON = 0-9
BUTTONSTYLEBUTTON =/ "All"
BUTTONSTYLEBUTTON =/ "Left"
BUTTONSTYLEBUTTON =/ "Right"
BUTTONSTYLEBUTTON =/ "Reset"
BUTTONSTYLEBUTTONSTATE = "ActiveUp"
BUTTONSTYLEBUTTONSTATE =/ "ActiveDown"
BUTTONSTYLEBUTTONSTATE =/ "InactiveUp"
BUTTONSTYLEBUTTONSTATE =/ "InactiveDown"
BUTTONSTYLEBUTTONSTATE =/ BUTTONSTYLEACTIVE
BUTTONSTYLEBUTTONSTATE =/ "Inactive"
BUTTONSTYLEBUTTONSTATE =/ TOGGLE
BUTTONSTYLEBUTTONSTATE =/ "AllActive"
BUTTONSTYLEBUTTONSTATE =/ "AllInactive"
BUTTONSTYLEBUTTONSTATE =/ "AllNormal"
BUTTONSTYLEBUTTONSTATE =/ "AllToggled"
BUTTONSTYLEBUTTONSTATE =/ "AllUp"
BUTTONSTYLEBUTTONSTATE =/ "AllDown"
BUTTONSTYLEBUTTONSTATE =/ "AllActiveUp"
BUTTONSTYLEBUTTONSTATE =/ "AllActiveDown"
BUTTONSTYLEBUTTONSTATE =/ "AllInactiveUp"
BUTTONSTYLEBUTTONSTATE =/ "AllInactiveDown"
BUTTONSTYLEACTIVE = "Active" ; - implies FOCUSED_WINDOW
BUTTONSTYLESTYLE = "Simple"
BUTTONSTYLESTYLE =/ "Default"
BUTTONSTYLESTYLE =/ "Solid"
BUTTONSTYLESTYLE =/ "Colorset"
BUTTONSTYLESTYLE =/ "Vector"
BUTTONSTYLESTYLE =/ BUTTONSTYLEGRADIENT
BUTTONSTYLESTYLE =/ "Pixmap"
BUTTONSTYLESTYLE =/ AdjustedPixmap"
BUTTONSTYLESTYLE =/ "ShrunkPixmap"
BUTTONSTYLESTYLE =/ "StretchedPixmap"
BUTTONSTYLESTYLE =/ "TiledPixmap"
BUTTONSTYLESTYLE =/ "MiniIcon"
BUTTONSTYLEGRADIENT = TYPE START-COLOUR END-COLOUR
BUTTONSTYLESTYLEFLAG =
	["!"] BUTTONSTYLESTYLEKEYWORD *("," ["!"] BUTTONSTYLESTYLEKEYWORD)
BUTTONSTYLESTYLEKEYWORD = "Raised"
BUTTONSTYLESTYLEKEYWORD =/ "Sunk"
BUTTONSTYLESTYLEKEYWORD =/ "Flat"
BUTTONSTYLESTYLEKEYWORD =/ "UseBorderStyle"
BUTTONSTYLESTYLEKEYWORD =/ "UseTitleStyle"
; (XXX = "Raised, Sunk, and Flat" can only be used initially!!!")
CMD_CHANGEMENUSTYLE = "ChangeMenuStyle" MENUSTYLENAME MENUNAME
CMD_CLEANUPCOLORSETS = "CleanupColorsets"
CMD_CLICKTIME = "ClickTime" POSINT
; (stores the negative value during startup>
CMD_CMD_CLASS_CLOSE = "Close" / "Delete" / "Destroy"
; work on context window
CMD_COLORMAPFOCUS = "ColormapFocus" ("FollowsMouse" / "FollowsFocus")
CMD_COLORSET = "Colorset" COLORSET_NUM COLORSETOPTION *("," COLORSETOPTION)
COLORSETOPTION = COLORSETKEYWORD [COLORSETVALUE]
COLORSETKEYWORD = "fg"
COLORSETKEYWORD =/ "Fore"
COLORSETKEYWORD =/ "Foreground"
COLORSETKEYWORD =/ "bg"
COLORSETKEYWORD =/ "Back"
COLORSETKEYWORD =/ "Background"
COLORSETKEYWORD =/ "hi"
COLORSETKEYWORD =/ "Hilite"
COLORSETKEYWORD =/ "Hilight"
COLORSETKEYWORD =/ "sh"
COLORSETKEYWORD =/ "Shade"
COLORSETKEYWORD =/ "Shadow"
COLORSETKEYWORD =/ "fgsh"
COLORSETKEYWORD =/ "Pixmap"
COLORSETKEYWORD =/ "TiledPixmap"
COLORSETKEYWORD =/ "AspectPixmap"
COLORSETKEYWORD =/ "Transparent"
COLORSETKEYWORD =/ "RootTransparent"
COLORSETKEYWORD =/ "Shape"
COLORSETKEYWORD =/ "TiledShape"
COLORSETKEYWORD =/ "AspectShape"
COLORSETKEYWORD =/ "NoShape"
COLORSETKEYWORD =/ ("V" / "B" / "D" / "S" / "C" / "R" / "Y") "Gradient"
COLORSETKEYWORD =/ "Tint"
COLORSETKEYWORD =/ "fgTint"
COLORSETKEYWORD =/ "bgTint"
COLORSETKEYWORD =/ "Alpha"
COLORSETKEYWORD =/ "fgAlpha"
COLORSETKEYWORD =/ "Dither"
COLORSETKEYWORD =/ "NoDither"
COLORSETKEYWORD =/ "IconTint"
COLORSETKEYWORD =/ "IconAlpha"
COLORSETKEYWORD =/ "Plain"
COLORSETVALUE = INT
COLORSETVALUE =/ COLORNAME
COLORSETVALUE =/ IMAGEFILENAME
COLORSETVALUE =/ INTPERCENTAGE
; (memory usage depends on highest colorset number)
COPYMENUSTYLE = "CopyMenuStyle" MENUSTYLENAME MENUSTYLENAME
CMD_CURSORMOVE = "CursorMove"
	CURSORMOVEDIM[CURSORMOVESUFFIX] CURSORMOVEDIM[CURSORMOVESUFFIX]
CURSORMOVEDIM = INT
CURSORMOVESUFFIX = "p"
CMD_CURSORSTYLE = "CursorStyle" CURSORSTYLECONTEXT [CURSORSTYLEXOPTION]
CURSORSTYLECONTEXT = CURSORSTYLEKEYWORD / CURSORSTYLEX11NAME
CURSORSTYLEKEYWORD = "POSITION"
CURSORSTYLEKEYWORD =/ "TITLE"
CURSORSTYLEKEYWORD =/ "DEFAULT"
CURSORSTYLEKEYWORD =/ "SYS"
CURSORSTYLEKEYWORD =/ "MOVE"
CURSORSTYLEKEYWORD =/ "RESIZE"
CURSORSTYLEKEYWORD =/ "WAIT"
CURSORSTYLEKEYWORD =/ "MENU"
CURSORSTYLEKEYWORD =/ "SELECT"
CURSORSTYLEKEYWORD =/ "DESTROY"
CURSORSTYLEKEYWORD =/ "TOP"
CURSORSTYLEKEYWORD =/ "RIGHT"
CURSORSTYLEKEYWORD =/ "BOTTOM"
CURSORSTYLEKEYWORD =/ "LEFT"
CURSORSTYLEKEYWORD =/ "TOP_LEFT"
CURSORSTYLEKEYWORD =/ "TOP_RIGHT"
CURSORSTYLEKEYWORD =/ "BOTTOM_LEFT"
CURSORSTYLEKEYWORD =/ "BOTTOM_RIGHT"
CURSORSTYLEKEYWORD =/ "TOP_EDGE"
CURSORSTYLEKEYWORD =/ "RIGHT_EDGE"
CURSORSTYLEKEYWORD =/ "BOTTOM_EDGE"
CURSORSTYLEKEYWORD =/ "LEFT_EDGE"
CURSORSTYLEKEYWORD =/ "ROOT"
CURSORSTYLEKEYWORD =/ "STROKE"
CURSORSTYLEKEYWORD =/ "None"
CURSORSTYLEKEYWORD =/ "Tiny"
CURSORSTYLEX11NAME = "top_left_corner"
CURSORSTYLEX11NAME =/ "top_left_arrow"
CURSORSTYLEX11NAME =/ "hand2"
CURSORSTYLEX11NAME =/ "fleur"
CURSORSTYLEX11NAME =/ "sizing"
CURSORSTYLEX11NAME =/ "watch"
CURSORSTYLEX11NAME =/ "crosshair"
CURSORSTYLEX11NAME =/ "pirate"
CURSORSTYLEX11NAME =/ "top_side"
CURSORSTYLEX11NAME =/ "bottom_side"
CURSORSTYLEX11NAME =/ "left_side"
CURSORSTYLEX11NAME =/ "top_right_corner"
CURSORSTYLEX11NAME =/ "bottom_left_corner"
CURSORSTYLEX11NAME =/ "top_side"
CURSORSTYLEX11NAME =/ "right_side"
CURSORSTYLEX11NAME =/ "left_side"
CURSORSTYLEX11NAME =/ "left_ptr"
CURSORSTYLEX11NAME =/ "plus"
CURSORSTYLEXOPTION = IMAGEFILE [INT]
CURSORSTYLEXOPTION =/ "fg"
CURSORSTYLEXOPTION =/ "bg"
CMD_DEFAULTCOLORS = "DefaultColors" [(COLOUR_FG] / "-") [(COLOUR_BG - "/")]
; XXX - We need to represent colour values here --- RGB.txt, etc.
CMD_DEFAULTCOLORSET = "DefaultColorset" (COLORSET_NUM / "-1")
CMD_DEFAULTFONT = "DefaultFont" [FONTNAME]
CMD_DEFAULTICON = "DefaultIcon" [IMAGEFILE]
CMD_DEFAULTLAYERS = "DefaultLayers" INT INT INT
CMD_DESCHEDULE = "Deschedule" [INT]
CMD_DESKTOPNAME = "DesktopName" INT DESKTOPNAME
DESKTOPNAME = 1*(ALPHA DIGIT)
CMD_DESKTOPSIZE = "DesktopSize" DESKTOPSIZDIM "x" DESKTOPSIZDIM
DESKTOPSIZEDIM = INT
CMD_DESTROYFUNC = "DestroyFunc" [FUNCNAME]
CMD_DESTROYMENU = "DestroyMenu" ["recreate"] MENUNAME
CMD_DESTROYMENUSTYLE = "DestroyMenuStyle" MENUSTYLENAME
CMD_DESTROYMODULECONFIG = "DestroyModuleConfig" MODULECONFIG
CMD_DESTROYSTYLE = "DestroyStyle" STYLENAME
CMD_DESTROYWINDOWSTYLE = "DestroyWindowStyle" ; operates on context window
CMD_ECHO = "Echo" RESTOFLINE
CMD_ECHOFUNCDEFINITION = "EchoFuncDefinition" FUNCNAME
CMD_EDGECOMMAND = "EdgeCommand" [DIRS_MAIN [RESTOFLINE_COMMAND]]
CMD_EDGELEAVECOMMAND = "EdgeLeaveCommand" [DIRS_MAIN [RESTOFLINE_COMMAND]]
CMD_EDGESCROLL = "EdgeScroll" EDGESCROLLDIM[EDGESCROLLSUFFIX]
	EDGESCROLLDIM[EDGESCROLLSUFFIX] [EDGESCROLLOPTION]
EDGESCROLLDIM = INT
EDGESCROLLSUFFIX = "p"
EDGESCROLLOPTION = "Wrap"
EDGESCROLLOPTION =/ "WrapX"
EDGESCROLLOPTION =/ "WrapY"
CMD_EDGETHICKNESS = "EdgeThickness" EDGETHICKNESSVAL
EDGETHICKNESSVAL = "0" / "1" / "2"
CMD_EMULATE = "Emulate" EMULATEVAL
EMULATEVAL = "Mvwm"
EMULATEVAL =/ "Mwm"
EMULATEVAL =/ "Win"
CMD_ESCAPEFUNC = "EscapeFunc"
CMD_EWMHBASESTRUTS = "EwmhBaseStruts" ["screen" XRANDRMONITORNAME] INT INT INT INT
CMD_EWMHNUMBEROFDESKTOPS = "EwmhNumberOfDesktops" ["screen" XRANDRMONITORNAME] INT INT
CMD_EXEC = "Exec" RESTOFLINE_COMMAND
CMD_EXECUSESHELL = "ExecUseShell" EXECUSESHELLSHELL
; Could technically be any external command; assume a value from /etc/shells
EXECUSESHELLSHELL = !!!
CMD_FAKECLICK = "FakeClick" FAKECLICKACTION *("," FAKECLICKACTION)
FAKECLICKACTION = FAKECLICKCOMMAND FAKECLICKVALUE
FAKECLICKCOMMAND = (FAKECLICKKEYWORD, FAKECLICKVALUE)
FAKECLICKKEYWORD = "press"
FAKECLICKKEYWORD =/ "release"
FAKECLICKKEYWORD =/ "modifiers"
FAKECLICKKEYWORD =/ "wait"
FAKECLICKKEYWORD =/ FAKECLICKDEPTH
FAKECLICKVALUE = "1"
FAKECLICKVALUE =/ "2"
FAKECLICKVALUE =/ "3"
FAKECLICKVALUE =/ "4"
FAKECLICKVALUE =/ "5"
FAKECLICKVALUE =/ "Mod1"
FAKECLICKVALUE =/ "Mod2"
FAKECLICKVALUE =/ "Mod3"
FAKECLICKVALUE =/ "Mod4"
FAKECLICKVALUE =/ "Mod5"
FAKECLICKVALUE =/ "6"
FAKECLICKVALUE =/ "7"
FAKECLICKVALUE =/ "8"
FAKECLICKVALUE =/ "Shift"
FAKECLICKVALUE =/ "Lock"
FAKECLICKVALUE =/ "Control"
FAKECLICKDEPTH = "depth"
FAKECLICKDEPTH =/ "0"
FAKECLICKDEPTH =/ "1"
FAKECLICKDEPTH =/ "2"
FAKECLICKDEPTH =/ "3"
FAKECLICKDEPTH =/ INT
CMD_FAKEKEYPRESS = "FakeKeypress" FAKEKEYPRESSACTION *("," FAKEKEYPRESSACTION)
FAKEKEYPRESSACTION = FAKEKEYPRESSCOMMAND FAKEKEYPRESSVALUE
FAKEKEYPRESSKEYWORD = "press"
FAKEKEYPRESSKEYWORD =/ "release"
FAKEKEYPRESSKEYWORD =/ "modifiers"
FAKEKEYPRESSKEYWORD =/ "wait"
FAKEKEYPRESSKEYWORD =/ DEPTH
FAKEKEYPRESSVALUE = KEYNAME
FAKEKEYPRESSDEPTH = "depth"
FAKEKEYPRESSDEPTH =/ "0"
FAKEKEYPRESSDEPTH =/ "1"
FAKEKEYPRESSDEPTH =/ "2"
FAKEKEYPRESSDEPTH =/ "3"
FAKEKEYPRESSDEPTH =/ INT
CMD_FLIPFOCUS = "FlipFocus" ["nowarp"]
CMD_FOCUS = "Focus" ["nowarp"]
CMD_FOCUSSTYLE = "FocusStyle" STYLEOPTIONS
CMD_FUNCTION = "Function" [FUNCNAME]
CMD_GOTODESK = "GotoDesk" DESKNUMBER
DESKNUMBER = ["prev" / (INT [INT [INT [INT]]])]
CMD_GOTODESKANDPAGE = "GotoDeskAndPage" "prev" / (INT INT INT)
CMD_GOTOPAGE = "GotoPage" PAGE_ARGUMENTS
PAGE_ARGUMENTS = ["prev" / ([OPTIONS] 2(PAGECCORD[PAGESUFFIX])
OPTIONS = ["!"] ("wrapx" / "wrapy" / "nodesklimitx" / "nodesklimity")
PAGECOORD = INT
PAGESUFFIX = "p"
CMD_HIDEGEOMETRYWINDOW = "HideGeometryWindow" [HIDEGEOMETRYWINDOWCOMMAND]
HIDEGEOMETRYWINDOWCOMMAND = "Never"
HIDEGEOMETRYWINDOWCOMMAND =/ "Move"
HIDEGEOMETRYWINDOWCOMMAND =/ "Resize"
CMD_HILIGHTCOLORSET = "HilightColorset" [COLORSET_NUM]
CMD_ICONIFY = "Iconify" BOOL_OR_TOGGLE
CMD_IGNOREMODIFIERS = "IgnoreModifiers" [ BINDINGMODIFIERS ]
CMD_IMAGEPATH = "ImagePath" [PATH]
CMD_INFOSTOREADD = "InfoStoreAdd" INFOSTOREKEY INFOSTOREVALUE
INFOSTOREKEY = STRING
INFOSTOREVALUE = STRING
CMD_INFOSTOREREMOVE = "InfoStoreRemove" [INFOSTOREREKEY]
CMD_KEEPRC = "KeepRc" [RESTOFLINE_COMMAND]
CMD_CLASS_KEY = ("Key" / "PointerKey") ["(" WINDOWSELECTOR ")"] KEYNAME
	BINDINGCONTEXT BINDINGMODIFIERS RESTOFLINE_COMMAND
CMD_KILLMODULE = "KillModule" [MODULENAME] [MODULEALIAS]
CMD_LAYER = "Layer" [INT INT] / "default"
CMD_LOCALEPATH = "LocalePath" [PATH]
CMD_CLASS_RAISELOWER = ("Lower" / "Raise" / "RaiseLower") ; operates on context window
CMD_MAXIMIZE = "Maximize" [MAXIMIZEFLAGS] [BOOL_OR_TOGGLE / "forget"]
	[[MAXIMIZEDIM[MAXIMIZESUFFIX]] MAXIMIZEDIM[MAXIMIZESUFFIX]]
MAXIMIZEGROWOPTS = "grow"
MAXIMIZEGROWOPTS =/ "growleft"
MAXIMIZEGROWOPTS =/ "growright"
MAXIMIZEGROWOPTS =/ "growup"
MAXIMIZEGROWOPTS =/ "growdown"
MAXIMIZEDIM = INT
MAXIMIZEDIM =/ MAXIMIZEGROWOPTS
MAXIMIZESUFFIX = "p"
MAXIMIZEFLAGS = "ewmhiwa"
MAXIMIZEFLAGS =/ "growonwindowlayer"
MAXIMIZEFLAGS =/ "growonlayers"
MAXIMIZEFLAGS =/ ("screen" / XINERAMASCR)
CMD_CLASS_MENU = ("Menu" / "Popup") MENUNAME [MENUPOSITION] [MENUCOMMAND]
MENUPOSITION = MENUCONTEXT_RECTANGLE INT INT [MENUOPTIONS]
MENUCONTEXT_RECTANGLE = "Root" !!!
MENUCONTEXT = "XineramaRoot"
MENUCONTEXT =/ "Mouse"
MENUCONTEXT =/ "Window"
MENUCONTEXT =/ "Interior"
MENUCONTEXT =/ "Title"
MENUCONTEXT =/ ("Button" INT) "Icon"
MENUCONTEXT =/ "Item"
MENUCONTEXT =/ "Context"
MENUCONTEXT =/ "This"
MENUCONTEXT =/ ("Rectangle" MENUCONTEXTGEOMETRY)
MENUOPTIONS = "TearoffImmediately"
MENUOPTIONS =/ "SelectInPlace"
MENUOPTIONS = !!!
MENUCONTEXTGEOMETRY = !!!
CMD_MENUSTYLE = "MenuStyle" MENUSTYLENAME *(["!"] MENUSTYLEOPTIONS)
MENUSTYLEOPTIONS = "Mvwm"
MENUSTYLEOPTIONS =/ "Mwm"
MENUSTYLEOPTIONS =/ "Win"
MENUSTYLEOPTIONS =/ "BorderWidth"
MENUSTYLEOPTIONS =/ "Foreground"
MENUSTYLEOPTIONS =/ "Background"
MENUSTYLEOPTIONS =/ "Greyed"
MENUSTYLEOPTIONS =/ "HilightBack"
MENUSTYLEOPTIONS =/ "HilightTitleBack"
MENUSTYLEOPTIONS =/ "ActiveFore"
MENUSTYLEOPTIONS =/ "MenuColorset"
MENUSTYLEOPTIONS =/ "ActiveColorset"
MENUSTYLEOPTIONS =/ "GreyedColorset"
MENUSTYLEOPTIONS =/ "TitleColorset"
MENUSTYLEOPTIONS =/ "Hilight3DThick"
MENUSTYLEOPTIONS =/ "Hilight3DThin"
MENUSTYLEOPTIONS =/ "Hilight3DOff"
MENUSTYLEOPTIONS =/ "Hilight3DThickness"
MENUSTYLEOPTIONS =/ "Animation"
MENUSTYLEOPTIONS =/ "Font"
MENUSTYLEOPTIONS =/ "TitleFont"
MENUSTYLEOPTIONS =/ "MenuFace"
MENUSTYLEOPTIONS =/ "PopupDelay"
MENUSTYLEOPTIONS =/ "PopupOffset"
MENUSTYLEOPTIONS =/ "TitleWarp"
MENUSTYLEOPTIONS =/ "TitleUnderlines0"
MENUSTYLEOPTIONS =/ "TitleUnderlines1"
MENUSTYLEOPTIONS =/ "TitleUnderlines2"
MENUSTYLEOPTIONS =/ "SeparatorsLong"
MENUSTYLEOPTIONS =/ "SeparatorsShort"
MENUSTYLEOPTIONS =/ "TrianglesSolid"
MENUSTYLEOPTIONS =/ "TrianglesRelief"
MENUSTYLEOPTIONS =/ "PopupImmediately"
MENUSTYLEOPTIONS =/ "PopupDelayed"
MENUSTYLEOPTIONS =/ "PopdownImmediately"
MENUSTYLEOPTIONS =/ "PopdownDelayed"
MENUSTYLEOPTIONS =/ "PopupActiveArea"
MENUSTYLEOPTIONS =/ "DoubleClickTime"
MENUSTYLEOPTIONS =/ "SidePic"
MENUSTYLEOPTIONS =/ "SideColor"
MENUSTYLEOPTIONS =/ "PopupAsRootMenu"
MENUSTYLEOPTIONS =/ "PopupAsSubmenu"
MENUSTYLEOPTIONS =/ "PopupIgnore"
MENUSTYLEOPTIONS =/ "PopupClose"
MENUSTYLEOPTIONS =/ "RemoveSubmenus"
MENUSTYLEOPTIONS =/ "HoldSubmenus"
MENUSTYLEOPTIONS =/ "SubmenusRight"
MENUSTYLEOPTIONS =/ "SubmenusLeft"
MENUSTYLEOPTIONS =/ "SelectOnRelease"
MENUSTYLEOPTIONS =/ "ItemFormat"
MENUSTYLEOPTIONS =/ "VerticalItemSpacing"
MENUSTYLEOPTIONS =/ "VerticalMargins"
MENUSTYLEOPTIONS =/ "VerticalTitleSpacing"
MENUSTYLEOPTIONS =/ "AutomaticHotkeys"
MENUSTYLEOPTIONS =/ "UniqueHotkeyActivatesImmediate"
MENUSTYLEOPTIONS =/ "MouseWheel"
MENUSTYLEOPTIONS =/ "ScrollOffPage"
MENUSTYLEOPTIONS =/ "TrianglesUseFore"
; add option syntax
CMD_CLASS_MODULE = ("Module" / "ModuleListenOnly") CMDMODULEARGS
CMDMODULEARGS = MODULENAME [MODULEALIAS]
CMD_MODULEPATH = "ModulePath" PATH
CMD_MODULESYNCHRONOUS = "ModuleSynchronous" ["Expect" STRING] ["Timeout" INT]
	CMDMODULEARGS
CMD_MODULETIMEOUT = "ModuleTimeout" INT
CMD_MOUSE = "Mouse" ["(" WINDOWSELECTOR ")"] BUTTON
	BINDINGCONTEXT BINDINGMODIFIERS COMMAND
CMD_MOVE = "Move" [MOVEARGS]
MOVEARGS = !!!
CMD_MOVETHRESHOLD = "MoveThreshold" [INT]
CMD_MOVETODESK = "MoveToDesk" DESKNUMBER
CMD_MOVETOPAGE = "MoveToPage" ["prev"] [MOVETOPAGEOPTIONS]
	2(MOVETOPAGECOORD[MOVETOPAGESUFFIX])
MOVETOPAGEOPTIONS = "wrapx" / "wrapy" / "nodesklimitx" / "nodesklimity"
MOVETOPAGECOORD = INT
MOVETOPAGESUFFIX = "p" / "w"
CMD_MOVETOSCREEN = "MoveToScreen" [XRANDRMONITORNAME]
XRANDRMONITORNAME = !!!
CMD_NOP = "Nop"
CMD_OPAQUEMOVESIZE = "OpaqueMoveSize" [INT]
CMD_PIPEREAD = "PipeRead" TOKEN ["quiet"]
CMD_PLACEAGAIN = "PlaceAgain" *("Anim" "Icon")
CMD_PLUS = "Plus" RESTOFLINE
CMD_PRINTINFO = "PrintInfo" PRINTINFOSUBJECT
PRINTINFOSUBJECT = (PRINTINFOKEYWORD [PRINTINFOVAL])
PRINTINFOVAL = "0"
PRINTINFOVAL =/ "1"
PRINTINFOVAL =/ "2"
PRINTINFOKEYWORD = "Colors"
PRINTINFOKEYWORD =/ "ImageCache"
PRINTINFOKEYWORD =/ "Locale"
PRINTINFOKEYWORD =/ "NLS"
PRINTINFOKEYWORD =/ "Style"
PRINTINFOKEYWORD =/ "Bindings"
PRINTINFOKEYWORD =/ "Infostore"
CMD_QUIT = "Quit"
CMD_QUITSCREEN = "QuitScreen"
CMD_READ = "Read" FILENAME ["quiet"]
CMD_CLASS_RECAPTURE = ("Recapture" / "RecaptureWindow")
CMD_CLASS_REFRESH = ("Refresh" / "RefreshWindow")
CMD_REPEAT = "Repeat" ["command"]
CMD_CLASS_RESIZE = ("Resize" / "ResizeMaximize") [RESIZEOPTS]
RESIZEOPTS = (RESIZEOPTS_BR / RESIZEOPTS_OTHER) [2RESIZEARG]
RESIZEOPTS_BR = ("bottomright" / "br") MOVEARGS
RESIZEOPTS_OTHER =
	("frame" / "fixeddirection" /
	("direction" (DIRS_CENTER / "automatic")) /
	("warptoborder" ["automatic"]))
RESIZEARG = "keep" / (RESIZEARG_2 [RESIZEARGSUFFIX])
RESIZEARG_2 = "w" / (["w"] RESIZEARGVAL)
RESIZEARGVAL = (SIGN INT) / POSINT
RESIZEARGSUFFIX = "p" / "c"
CMD_CLASS_RESIZEMOVE = ("ResizeMove" / "ResizeMoveMaximize")
	RESIZEOPTS MOVEARGS
CMD_RESTACKTRANSIENTS = "RestackTransients"
CMD_RESTART = "Restart" [STRING]
CMD_SCHEDULE = "Schedule" ["periodic"] INT [INT] RESTOFLINE_COMMAND
CMD_SCROLL = "Scroll"
	[(SCROLLDIM[SCROLLSUFFIX] SCROLLDIM[SCROLLSUFFIX]) / OPTION]
SCROLLDIM = INT
OPTION = "reverse"
SCROLLSUFFIX = "p"
CMD_SENDTOMODULE = "SendToModule" [MODULENAME] [STRING]
CMD_SETANIMATION = "SetAnimation" INT [INT]
CMD_SILENT = "Silent" RESTOFLINE_COMMAND
CMD_STATE = "State" STATENUM [BOOL]
CMD_CLASS_STICK = ("Stick" / "StickAcrossDesks" / "StickAcrossPages")
	[BOOL_OR_TOGGLE]
CMD_CLASS_STYLE = ("Style" / "WindowStyle") [STYLENAME] [STYLEOPTIONS]
; note: WindowStyle operates on context window
STYLEOPTIONS = STYLEOPTION ("," STYLEOPTION)
STYLEOPTION = !!!
CMD_TEARMENUOFF = "TearMenuOff"
; note: applies to menu context only
; note: ignores all arguments
; note: syntax description complete
CMD_TITLE = "Title"
; note: applies to menu context only
; note: ignores all arguments
; note: syntax description complete
CMD_TITLESTYLE = "TitleStyle"
;!!!
CMD_SETENV = "SetEnv" [TOKEN_ENVVAR [TOKEN_ENVVAL]]
TOKEN_ENVVAR = TOKEN
TOKEN_ENVVAL = TOKEN
; note: does nothing if no arguments are given
; note: uses an empty value string if the second argument is missing
; note: ignores rest of line
; note: syntax description complete
CMD_UNSETENV = "UnsetEnv" [TOKEN_ENVVAR]
; note: does nothing if argument is missing
; note: ignores rest of line
; note: syntax description complete
CMD_UPDATESTYLES = "UpdateStyles"
; note: ignores rest of line
; note: syntax description complete
CMD_WAIT = "Wait" [TOKEN_WAIT_PATTERN [STRIPPED_RESTOFLINE]]
; Note: The first argument, or - if present - the rest of the line is used as
; the pattern to wait for.
; note: the syntax with more than one argument is not documented.  Comment in
; the sources call it the "old syntax".
; note: syntax description complete
CMD_WARPTOWINDOW = "WarpToWindow" [PERCENT_ARG_PAIR]
; note: arguments not used when used on an unmanaged window
; note: arguments are ignored if not valid
; note: ignores rest of line
; note: syntax description complete
;!!!todo
CMD_WINDOWLIST = "WindowList" ["(" WINDOWLISTCONDITIONS ")"]
	[WINDOWLISTPOSITION] [WINDOWLLISTOPTIONS] [COMMAND]
WINDOWLISTPOSITION = WINDOWLISTCONTEXT_RECTANGLE INT INT
	[WINDOWLISTCONTEXTOPTIONS]
WINDOWLISTCONTEXT_RECTANGLE = "Root"
WINDOWLISTCONTEXT_RECTANGLE =/ "XineramaRoot"
WINDOWLISTCONTEXT_RECTANGLE =/ "Mouse"
WINDOWLISTCONTEXT_RECTANGLE =/ "Window"
WINDOWLISTCONTEXT_RECTANGLE =/ "Interior"
WINDOWLISTCONTEXT_RECTANGLE =/ "Tiitle"
WINDOWLISTCONTEXT_RECTANGLE =/ ("Button" INT)
WINDOWLISTCONTEXT_RECTANGLE =/ "Icon"
WINDOWLISTCONTEXT_RECTANGLE =/ "Item"
WINDOWLISTCONTEXT_RECTANGLE =/ "Context"
WINDOWLISTCONTEXT_RECTANGLE =/ "This"
WINDOWLISTCONTEXT_RECTANGLE =/ ("Rectangle" GEOMETRY)
WINDOWLISTCONTEXTOPTIONS = "TearoffImmediately"
WINDOWLISTCONTEXTOPTIONS =/ "SelectInPlace"
WINDOWLISTOPTIONS = (WINDOWLISTKEYWORD [WINDOWLISTVALUE])
WINDOWLISTOPTIONS = "Geometry"
WINDOWLISTOPTIONS =/ "NoGeometry"
WINDOWLISTOPTIONS =/ "NoGeometryWithInfo"
WINDOWLISTOPTIONS =/ "NoDeskNum"
WINDOWLISTOPTIONS =/ "NoLayer"
WINDOWLISTOPTIONS =/ "NoNumInDeskTitle"
WINDOWLISTOPTIONS =/ "NoCurrentDeskTitle"
WINDOWLISTOPTIONS =/ ("MaxLabelWidth" INT)
WINDOWLISTOPTIONS =/ "TitleForAllDesks"
WINDOWLISTOPTIONS =/ ("Function" FUNCNAME)
WINDOWLISTOPTIONS =/ ("Desk" INT)
WINDOWLISTOPTIONS =/ "CurrentDesk"
WINDOWLISTOPTIONS =/ "NoIcons"
WINDOWLISTOPTIONS =/ "Icons"
WINDOWLISTOPTIONS =/ "OnlyIcons"
WINDOWLISTOPTIONS =/ "NoNormal"
WINDOWLISTOPTIONS =/ "Normal"
WINDOWLISTOPTIONS =/ "OnlyNormal"
WINDOWLISTOPTIONS =/ "NoSticky"
WINDOWLISTOPTIONS =/ "Sticky"
WINDOWLISTOPTIONS =/ "OnlySticky"
WINDOWLISTOPTIONS =/ "NoStickyAcrossPages"
WINDOWLISTOPTIONS =/ "StickyAcrossPages"
WINDOWLISTOPTIONS =/ "OnlyStickyAcrossPages"
WINDOWLISTOPTIONS =/ "NoStickyAcrossDesks"
WINDOWLISTOPTIONS =/ "StickyAcrossDesks"
WINDOWLISTOPTIONS =/ "OnlyStickyAcrossDesks"
WINDOWLISTOPTIONS =/ "NoOnTop"
WINDOWLISTOPTIONS =/ "OnTop"
WINDOWLISTOPTIONS =/ "OnlyOnTop"
WINDOWLISTOPTIONS =/ "NoOnBottom"
WINDOWLISTOPTIONS =/ "OnlyOnBottom"
WINDOWLISTOPTIONS =/ (Layer INT [INT])
WINDOWLISTOPTIONS =/ "UseSkipList"
WINDOWLISTOPTIONS =/ "OnlySkipList"
WINDOWLISTOPTIONS =/ "SortByResource"
WINDOWLISTOPTIONS =/ "SortByClass"
WINDOWLISTOPTIONS =/ "NoHotKeys"
WINDOWLISTOPTIONS =/ "SelectOnRelease"
WINDOWLISTOPTIONS =/ "ReverseOrder"
WINDOWLISTOPTIONS =/ "NoDeskSort"
WINDOWLISTOPTIONS =/ "CurrentAtEnd"
WINDOWLISTOPTIONS =/ "IconifiedAtEnd"
WINDOWLISTOPTIONS =/ "UseIconName"
WINDOWLISTOPTIONS =/ "Alphabetic"
WINDOWLISTOPTIONS =/ "NotAlphabetic"
WINDOWLISTKEYWORD = !!!
WINDOWLISTVALUE = !!!
; note: !!! to do
CMD_WINDOWSHADE = "WindowShade" ["shadeagain"]
	["last" / DIRS_MINOR] [WINDOWSHADEMODE]
WINDOWSHADEMODE = WINDOWSHADETOGGLE / WINDOWSHADEON / WINDOWSHADEOFF
WINDOWSHADETOGGLE = () / TOGGLE
WINDOWSHADEON = TRUE
WINDOWSHADEOFF = FALSE / "2"
; note: defaults to toggle
; note: if "last" or DIRS_MINOR is present and valid, ignore the
;       WINDOWSHADEMODE argument if present
; note: ignores rest of line
; note: syntax description complete
CMD_XSYNC = "XSync"
; note: ignores all arguments
; note: syntax description complete
CMD_XSYNCHRONIZE = "XSynchronize" [BOOL_OR_TOGGLE_DEFAULT_TOGGLE]
; note: argument defaults to toggle if missing or invalid
; note: ignores rest of line
; note: syntax description complete
CMD_XORPIXMAP = "XorPixmap" [IMAGEFILE]
; note: if argument is missing, maps to "XorValue 0"
; note: ignores rest of line
; note: syntax description complete
CMD_XORVALUE = "XorValue" [INTEGER_ARGUMENT]
; note: argument defaults to 0 if missing or malformed
; note: argument is converted to unsinged long before use
; note: argument should be parsed as unsigned long to prevent misinterpretation
; note: ignores rest of line
; note: syntax description complete
;; decor commands

CMD_ADDTODECOR = "AddToDecor" [TOKEN_DECORNAME] RESTOFLINE_COMMAND
; note: does nothing if the decor name is missing
; note: if no decor with that name exists, creates a new one
; note: adds the command to the decor
; note: syntax description complete

CMD_CHANGEDECOR = "ChangeDecor" [TOKEN_DECORNAME]
; note: does nothing if no decor name is given
; note: ignores rest of line
; note: syntax description complete
; note: operates on current window

CMD_DESTROYDECOR = "DestroyDecor" ["recreate"] [TOKEN_DECORNAME]
; note: does nothing if no decor name is given
; note: ignores rest of line
; note: syntax description complete

CMD_UPDATEDECOR = "UpdateDecor" [TOKEN_DECORNAME]
; note: updates all decors if decor name is missing
; note: ignores rest of line
; note: syntax description complete
;; conditional commands

CMD_BREAK = "Break" [BREAKLEVELS]
BREAKLEVELS = INT
; note: uses -1 if BREAKLEVELS is missing or invalid (<= 0)
; note: syntax description complete
CMD_CLASS_PICK = ("ThisWindow" / "Pick" / "PointerWIndow" )
	[SELECTCMDCONDITION] RESTOFLINE_COMMAND
; note: syntax description complete
CMD_ALL = "All" [ALLOPTIONS] [SELECTCMDCONDITION] RESTOFLINE_COMMAND
ALLOPTIONS = "Reverse"
ALLOPTIONS =/ "UseStack"
; note: syntax description complete
CMD_NOWINDOW = "NoWindow" RESTOFLINE_COMMAND
; note: executes the command without a window context
; note: syntax description complete
CMD_CLASS_CIRCULATE = ("Any" / "Current" / "Next" / "None" / "Prev")
	[SELECTCMDCONDITION] RESTOFLINE_COMMAND
; note: syntax description complete
CMD_DIRECTION = "Direction" ["FromPointer"] DIRS_CENTER
	[SELECTCMDCONDITION] RESTOFLINE_COMMAND
; note: syntax description complete
CMD_SCANFORWINDOW = "ScanForWindow" ["FromPointer"] DIRS_MAIN DIRS_MAIN
	[SELECTCMDCONDITION] RESTOFLINE_COMMAND
; note: syntax description complete
CMD_WINDOWID = "WindowId"
	[("root" [WINDOWIDSCREENNUM]) / (WINDOWID [SELECTCMDCONDITION])]
	RESTOFLINE_COMMAND
; does nothing if no argument is given of the window id is invalid
; note: syntax description complete
WINDOWIDSCREENNUM = POSINT
; note: valid range is 0 to <number of screens - 1>
; note: mvwm has replaced Xinerama with XRandr, therfore using integets to
;       refer to monitors won't work.
WINDOWID = LONGINT
; note: long value parsed by strtol without error checking
CMD_TEST = "Test" TESTCMDCONDITION RESTOFLINE_COMMAND
TESTCMDCONDITIONSTRING = [STRING_IN_BRACES / STRING_IN_PARENTHESES]
; note: the STRING_IN_... is then parsed with the TESTCMDCONDITIONS rule
TESTCMDCONDITIONS = STRING_COMMA_TERMINATED *["," STRING_COMMA_TERMINATED]
; note: the TESTCMDCONDITIONS is then parsed with the TESTCMDCONDNEG rule
TESTCMDCONDNEG = ["!"] TESTCMDCOND
TESTCMDCOND = ("version" ((TOKEN_TESTCMDOPERATOR VERSION) / TOKEN_VERSIONPATTERN))
TESTCMDCOND =/ ("EnvIsSet" TOKEN_ENVVAR)
TESTCMDCOND =/ ("EnvMatch" ENVMATCHARG)
TESTCMDCOND =/ (("EdgeHasPointer" / "EdgeIsActive") (DIRS_MAIN / "Any"))
TESTCMDCOND =/ ("Start" / "Init" / "Restart" / "Exit" / "Quit" / "ToRestart")
TESTCMDCOND =/ ("True" / "False")
TESTCMDCOND =/ (("F" / "R" / "W" / "X" / "I") "," FILENAME)
TOKEN_TESTCMDOPERATOR = ">=" / ">" / "<=" / "==" / "!="
ENVMATCHARG = ("infostore."INFOSTOREKEY) / TOKEN_ENVVAR
TESTCMDVERSIONPATTERN = TOKEN
; note: TESTCMDVERSIONPATTERN is compared to the version string (x.y.z) and may
; contain wildcards.
CMD_TESTRC = "TestRc" [STRING_IN_BRACES / STRING_IN_PARENTHESES]
	RESTOFLINE_COMMAND
TESRRCRCNEG = ["!"] TESTRCRC
TESTRCRC =  "1" / "match"
TESTRCRC =/ "0" / "nomatch"
TESTRCRC =/ "-1" / "error"
TESTRCRC =/ "-2" / "break"
; note: the STRING_IN_... is then parsed with the TESTRCRC rule
; note: does nothing if no command is given
: note: the condition inside the braces or parentheses may contain quoted
; note: syntax description complete
;; !!! more common rules

; Integer arguments as parsed by GetIntegerArguments()
INTEGER_ARGUMENT = INT

; Loaded by PictureFindImageFile
IMAGEFILE = TOKEN
; note: if file not found, try again with IMAGEFILE ".gz"
; parsed by parse_gravity_argument
DIR_N = "-" / "N" / "North" / "Top" / "t" / "Up" / "u"
DIR_E = "]" / "E" / "East" / "Right" / "r" / "Right" / "r"
DIR_S = "_" / "S" / "South" / "Bottom" / "b" / "Down" / "d"
DIR_W = "[" / "W" / "West" / "Left" / "l" / "Left" / "l"
DIR_NE = "^" / "NE" / "NorthEast" / "TopRight" / "tr" / "UpRight" / "ur"
DIR_SE = ">" / "SE" / "SouthEast" / "BottomRight" / "br" / "DownRight" / "dr"
DIR_SW = "v" / "SW" / "SouthWest" / "BottomLeft" / "bl" / "DownLeft" / "dl"
DIR_NE = "<" / "NW" / "NorthWest" / "TopLeft" / "tl" / "UpLeft" / "ul"
DIR_C = "." / "C" / "Center" / "Centre"
DIRS_MAJOR = DIR_N / DIR_E / DIR_S / DIR_W
DIRS_MINOR = DIRS_MAIN / DIR_NE / DIR_SE / DIR_SW / DIR_NW
DIRS_ALL = DIRS_MAIN / DIRS_DIAG / DIR_C
; Parsed by ParseToggleArgument
BOOL_OR_TOGGLE_DEFAULT_TOGGLE = BOOL / TOGGLE
BOOL_OR_TOGGLE_DEFAULT_TRUE = BOOL / TOGGLE
BOOL_OR_TOGGLE_DEFAULT_FALSE = BOOL / TOGGLE
BOOL_DEFAULT_TRUE = BOOL
BOOL_DEFAULT_FALSE = BOOL
; parsed by strtol
LONGINT = INT
; parsed by select_cmd()
SELECTCMDCONDITION = [STRING_IN_BRACES / STRING_IN_PARENTHESES]
; note: the STRING_IN_... is then parsed with the CONDITIONMASK rule
; parsed by CreateFlagString
CONDITIONMASK = [CM_COND_NEG *("," CM_COND_NEG)]
CM_COND_NEG = ["!"] CM_COND
CM_COND = ("AcceptsFocus")
CM_COND =/ ("Focused")
CM_COND =/ ("HasPointer")
CM_COND =/ ("Iconic")
CM_COND =/ ("Visible")
CM_COND =/ ("Overlapped")
CM_COND =/ ("PlacedByButton" [BUTTON])
CM_COND =/ ("PlacedByButton3")
CM_COND =/ ("Raised")
CM_COND =/ ("Sticky")
CM_COND =/ ("StickyAcrossPages")
CM_COND =/ ("StickyAcrossDesks")
CM_COND =/ ("StickyIcon")
CM_COND =/ ("StickyAcrossPagesIcon")
CM_COND =/ ("StickyAcrossDesksIcon")
CM_COND =/ ("Maximized")
CM_COND =/ ("FixedSize")
CM_COND =/ ("FixedPosition")
CM_COND =/ ("HasHandles")
CM_COND =/ ("Iconifiable")
CM_COND =/ ("Maximizable")
CM_COND =/ ("Closable")
CM_COND =/ ("Shaded")
CM_COND =/ ("Transient")
CM_COND =/ ("PlacedByMvwm")
CM_COND =/ ("CurrentDesk")
CM_COND =/ ("CurrentPage")
CM_COND =/ ("CurrentGlobalPage")
CM_COND =/ ("CurrentPageAnyDesk")
CM_COND =/ ("CurrentScreen")
CM_COND =/ ("AnyScreen")
CM_COND =/ ("CurrentGlobalPageAnyDesk")
CM_COND =/ ("CirculateHit")
CM_COND =/ ("CirculateHitIcon")
CM_COND =/ ("CirculateHitShaded")
CM_COND =/ ("State" STATENUM)
CM_COND =/ ("Layer" [INT])
; argument is the layer number; negative values are silently ignored
CM_COND =/ NAMELIST
CM_NAMELIST = NAME *["|" NAME]
CM_NAME = STRING
; up to and excluding next "|"
QUOTED_TOKEN = TOKEN
STATENUM = DIGIT / ("1" DIGIT) / ("2" DIGIT) / "30" / "31"
; Parsed by GetOnePercentArgument()
PERCENT_ARG = INT [PERCENT_ARG_SUFFIX]
PERCENT_ARG_SUFFIX = "p" / "P"
; Parsed by GetTwoPercentArguments()
PERCENT_ARG_PAIR = 2PERCENT_ARG / RECTANGLE_ARGS
; Parsed by GetRectangleArguments()
RECTANGLE_ARGS = INT RECT_CHARACTER INT
RECT_CHARACTER = %x01-09 / %x0b-4f / %x51-6f / %x71-ff
; note: any character except p, P and \n.
DQ_RECT_CHARACTER = %x01-09 / %x0b-4f / %x51-6f / %x71-ff
;; string rules

DQUOTE = %x22 ; "
SQUOTE = %x27 ; '
BQUOTE = %x60 ; `
CQUOTE = %x5c ; \

; any character except \, ", ', `, whitespace, newline
SCHAR_UNQ = %x01-08
SCHAR_UNQ =/ %x0b-1f
SCHAR_UNQ =/ %x21
SCHAR_UNQ =/ %x23-26
SCHAR_UNQ =/ %x28-5b
SCHAR_UNQ =/ %x5d-5f
SCHAR_UNQ =/ %x61-ff

; any character except \, ", ', `, ), whitespace, newline
SCHAR_UNQ_NO_CPAREN = %x01-08
SCHAR_UNQ_NO_CPAREN =/ %x0b-1f
SCHAR_UNQ_NO_CPAREN =/ %x21
SCHAR_UNQ_NO_CPAREN =/ %x23-26
SCHAR_UNQ_NO_CPAREN =/ %x28
SCHAR_UNQ_NO_CPAREN =/ %x2a-5b
SCHAR_UNQ_NO_CPAREN =/ %x5d-5f
SCHAR_UNQ_NO_CPAREN =/ %x61-ff

; any character except \, ", ', `, ], whitespace, newline
SCHAR_UNQ_NO_CBRACE = %x01-08
SCHAR_UNQ_NO_CBRACE =/ %x0b-1f
SCHAR_UNQ_NO_CBRACE =/ %x21
SCHAR_UNQ_NO_CBRACE =/ %x23-26
SCHAR_UNQ_NO_CBRACE =/ %x28-5b
SCHAR_UNQ_NO_CBRACE =/ %x5e-5f
SCHAR_UNQ_NO_CBRACE =/ %x61-ff

; any character except \, ", ', `, comma, whitespace, newline
SCHAR_UNQ_NO_COMMA = %x01-08
SCHAR_UNQ_NO_COMMA =/ %x0b-1f
SCHAR_UNQ_NO_COMMA =/ %x21
SCHAR_UNQ_NO_COMMA =/ %x23-26
SCHAR_UNQ_NO_COMMA =/ %x28-2b
SCHAR_UNQ_NO_COMMA =/ %x2d-5b
SCHAR_UNQ_NO_COMMA =/ %x5d-5f
SCHAR_UNQ_NO_COMMA =/ %x61-ff

; \ followed by any character except newline
SCHAR_CQ_CHAR = "\" (%x01-09 /%x0b-ff)

; any character except ", whitespace, newline (\ quotes resolved)
SCHAR_DQ = SCHAR_UNQ
SCHAR_DQ =/ SQUOTE
SCHAR_DQ =/ BQUOTE
SCHAR_DQ =/ SCHAR_CQ_CHAR
; any character except ', whitespace, newline (\ quotes resolved)
SCHAR_SQ = SCHAR_UNQ
SCHAR_SQ =/ DQUOTE
SCHAR_SQ =/ BQUOTE
SCHAR_SQ =/ SCHAR_CQ_CHAR
; any character except `, whitespace, newline (\ quotes resolved)
SCHAR_BQ = SCHAR_UNQ
SCHAR_BQ =/ DQUOTE
SCHAR_BQ =/ SQUOTE
SCHAR_BQ =/ SCHAR_CQ_CHAR
; any simple character or one quoted with \
SCHAR_CQ = SCHAR_UNQ
SCHAR_CQ =/ SCHAR_CQ_CHAR
; unquoted string
STRING_UNQ = 1*SCHAR_UNQ
STRING_UNQ_NO_CPAREN = 1*SCHAR_UNQ_NO_CPAREN
STRING_UNQ_NO_CBRACE = 1*SCHAR_UNQ_NO_CBRACE
STRING_UNQ_NO_COMMASTRING_UNQ_NO_COMMA = 1*SCHAR_UNQ_NO_COMMA
; strings quoted with ", ', `
STRING_DQ = DQUOTE 1*SCHAR_DQ DQUOTE
STRING_SQ = SQUOTE 1*SCHAR_SQ SQUOTE
STRING_BQ = BQUOTE 1*SCHAR_BQ BQUOTE
STRING_Q_PAIR = STRING_DQ / STRING_SQ / STRING_BQ

STRING = 1*(STRING_UNQ / STRING_DQ / STRING_SQ / STRING_BQ)
TOKEN = STRING

; a string with embedded whitespace enclosed in [] used in condigions
STRING_IN_BRACES = *WS
	"[" *(STRING_UNQ_NO_CBRACE / STRING_Q_PAIR / 1*WSC) "]"
; a string with embedded whitespace enclosed in () used in conditions
STRING_IN_PARENTHESES = *WS
	"[" *(STRING_UNQ_NO_CPAREN / STRING_Q_PAIR / 1*WSC) "]"
; a string with embedded whitespace terminated by an unquoted comma
STRING_COMMA_TERMINATED = *(STRING_UNQ_NO_COMMA / STRING_Q_PAIR / 1*WSC)
;; !!! obsolete commands removed in mvwm

CMD_GNOMEBUTTON = "GnomeButton"
CMD_GNOMESHOWDESKS = "GnomeShowDesks"
CMD_SAVESESSION = "SaveSession"
CMD_SAVEQUITSESSION = "SaveQuitSession"
CMD_STROKE = "Stroke"
CMD_STROKEFUNC = "StrokeFunc"
CMD_QUITSESSION = "QuitSession"
CMD_XINERAMA = "Xinerama"
CMD_XINERAMAPRIMARYSCREEN = "XineramaPrimaryScreen"
CMD_XINERAMASLS = "XineramaSls"
CMD_XINERAMASLSSCREENS = "XineramaSlsScreens"
CMD_XINERAMASLSSIZE = "XineramaSlsSize"

;; !!! obsolete commands in fvwm2

CMD_COLORLIMIT = "ColorLimit"
CMD_WINDOWFONT = "WindowFont" ; Style * Font ...
CMD_WINDOWSHADEANIMATE = "WindowShadeAnimate" ; Style * WindowShadeSteps
CMD_WINDOWSDESK = "WindowsDesk" ; See 'MoveToDesk'
CMD_DESK = "Desk" ; See 'Gotodesk'
CMD_EDGERESISTANCE = "EdgeResistance" ; Style * EdgeMoveDelay, EdgeMoveResistance
CMD_GLOBALOPTS = "GlobalOpts" ; Various Style options
CMD_HILIGHTCOLOR = "HilightColor" ; Style
CMD_ICONFONT = "IconFont" FONTNAME ; Style
CMD_ICONPATH = "IconPath" ; ImagePath
CMD_PIXMAPPATH = "PixmapPath" ; ImagePath
CMD_SNAPATTRACTION = "SnapAttraction" ; Style * SnapAttraction
CMD_SNAPGRID = "SnapGrid" ; Style * SnapGrid