protected static function calculateVariables()
 {
     $regex = self::$regex;
     // In-file variables override global variables
     // Runtime variables override in-file variables
     self::$storage->variables = array_merge(self::$globalVars, self::$storage->variables);
     if (!empty(self::$options['vars'])) {
         self::$storage->variables = array_merge(self::$storage->variables, self::$options['vars']);
     }
     // Place variables referenced inside variables
     // Excecute any custom functions
     foreach (self::$storage->variables as $name => &$value) {
         // Referenced variables
         $value = preg_replace_callback($regex->function->var, array('self', 'cb_placeVariables'), $value);
         // Custom functions:
         //   Variable values can be escaped from function parsing with a double bang
         if (strpos($value, '!!') === 0) {
             $value = ltrim($value, "!\t\r ");
         } else {
             $value = csscrush_function::parseAndExecuteValue($value);
         }
     }
 }
 public static function init()
 {
     // Set the custom function regex pattern
     self::$functionList = self::getFunctions();
     self::$functionPatt = '!(^|[^a-z0-9_-])(' . implode('|', self::$functionList) . ')?\\(!i';
 }
 public function __construct($selector_string = null, $declarations_string)
 {
     $regex = csscrush::$regex;
     // Parse the selectors chunk
     if (!empty($selector_string)) {
         $selectors_match = csscrush_util::splitDelimList($selector_string, ',');
         $this->parens += $selectors_match->matches;
         // Remove and store comments that sit above the first selector
         // remove all comments between the other selectors
         preg_match_all($regex->token->comment, $selectors_match->list[0], $m);
         $this->comments = $m[0];
         foreach ($selectors_match->list as &$selector) {
             $selector = preg_replace($regex->token->comment, '', $selector);
             $selector = trim($selector);
         }
         $this->selectors = $selectors_match->list;
     }
     // Apply any custom functions
     $declarations_string = csscrush_function::parseAndExecuteValue($declarations_string);
     // Parse the declarations chunk
     // Need to split safely as there are semi-colons in data-uris
     $declarations_match = csscrush_util::splitDelimList($declarations_string, ';');
     $this->parens += $declarations_match->matches;
     // Parse declarations in to property/value pairs
     foreach ($declarations_match->list as $declaration) {
         // Strip comments around the property
         $declaration = preg_replace($regex->token->comment, '', $declaration);
         // Store the property
         $colonPos = strpos($declaration, ':');
         if ($colonPos === false) {
             // If there is no colon it's malformed
             continue;
         }
         // The property name
         $prop = trim(substr($declaration, 0, $colonPos));
         // Test for escape tilde
         if ($skip = strpos($prop, '~') === 0) {
             $prop = substr($prop, 1);
         }
         // Store the property name
         $this->addProperty($prop);
         // Store the property family
         // Store the vendor id, if one is present
         if (preg_match($regex->vendorPrefix, $prop, $vendor)) {
             $family = $vendor[2];
             $vendor = $vendor[1];
         } else {
             $vendor = null;
             $family = $prop;
         }
         // Extract the value part of the declaration
         $value = substr($declaration, $colonPos + 1);
         $value = $value !== false ? trim($value) : $value;
         if ($value === false or $value === '') {
             // We'll ignore declarations with empty values
             continue;
         }
         // Create an index of all functions in the current declaration
         if (preg_match_all($regex->function->match, $value, $functions) > 0) {
             // csscrush::log( $functions );
             $out = array();
             foreach ($functions[2] as $index => $fn_name) {
                 $out[] = $fn_name;
             }
             $functions = array_unique($out);
         } else {
             $functions = array();
         }
         // Store the declaration
         $_declaration = (object) array('property' => $prop, 'family' => $family, 'vendor' => $vendor, 'functions' => $functions, 'value' => $value, 'skip' => $skip);
         $this->declarations[] = $_declaration;
     }
 }