示例#1
0
///////////////////////////////////////////////////////////////////////////////////////  
/// Callback functions called by the XML parser. It creates and push a new element node.
/// This is the start handler of Parser. XML_Parse() starts from here.
///
///\param context
///\param elm The element
///\param attr The attributes
/////////////////////////////////////////////////////////////////////////////////////// 
static void XMLCALL startElement(void *context, const char *elm, const char **attr) {
    Elm el;
    void* e;
    int size;
    el = checkElement(elm);  //Get the index of element
    printfDebug("startElement():%s\n", elm);
    printfDebug("*** starting element %s\n", elmNames[el]);
    if (el==-1) { 
      printDebug("Error!"); 
      return; // error
    }
    skipData = (el != elm_Name); // skip element content for all elements but Name

    switch(getAstNodeType(el)){
        case astElement:          size = sizeof(Element); break;
        case astListElement:      size = sizeof(ListElement); break;
        case astType:             size = sizeof(Type); break;
        case astScalarVariable:   size = sizeof(ScalarVariable); break;
        case astModelDescription: size = sizeof(ModelDescription); break;
		default: assert(0);  // Error message if there is no matching element,
    }

    printfIntDebug("Start to created a new element with size: %d\n", size);
    e = newElement(el, size, attr);  // Create a new element
    printDebug("Created a new element");

    if(checkPointer(e)) assert(0); // Check the validity of the new element
    printDebug("startElement(): Start to stack push.");
    stackPush(stack, e); // Add the element to stack and grow the stack if necessary
}
示例#2
0
///////////////////////////////////////////////////////////////////////////////
/// Add Attributes to an given element.
/// It copies the \c attr array and all values, 
/// replaces all attribute names by constant literal strings,
/// converts the null-terminated array into an array of known size n.
///
///\param el The element. 
///\param attr Attributes.
///\returns 0 if there is no error occurred. Otherwise, return 1 to indicate an error.
///////////////////////////////////////////////////////////////////////////////
int addAttributes(Element* el, const char** attr) {
    int n, a;
    const char** att = NULL;
    for (n=0; attr[n]; n+=2);
    printDebug("\n");
    printfIntDebug("addAttributes(): n = %d\n", n); 
    if (n>0) {
          att = calloc(n, sizeof(char*));
          if (checkPointer(att)) return 1;
      } 
    printDebug("addAttributes(): allocated att"); 

    for (n=0; attr[n]; n+=2) {
        char* value = strdup(attr[n+1]); //duplicate string attr[n+1]
         printfDebug("addAttributes(): value = %s\n", value);

        if (checkPointer(value)) return 1;
        a = checkAttribute(attr[n]);
        printfIntDebug("addAttributes(): index a = %d\n", a); 

        if (a == -1) {
          printf("Illegal attribute in"); 
          return 1;  // illegal attribute error
        }
        att[n  ] = attNames[a]; // no heap memory
        printfDebug("addAttributes(): attNames = %s\n", attNames[a]); 

        att[n+1] = value;       // heap memory
        printfDebug("addAttributes(): att[n+1] = %s\n", att[n+1]	); 
        
    }
    el->attributes = att; // NULL if n=0
    el->n = n;
    return 0; // success
}
示例#3
0
文件: extgl.c 项目: 2048Studio/lwjgl
bool extgl_QueryExtension(const GLubyte*extensions, const char *name)
{
	const GLubyte *start;
	GLubyte *where, *terminator;

	if (extensions == NULL) {
		printfDebug("NULL extension string\n");
		return false;
	}

	/* Extension names should not have spaces. */
	where = (GLubyte *) strchr(name, ' ');
	if (where || *name == '\0')
		return false;

	/* It takes a bit of care to be fool-proof about parsing the
		 OpenGL extensions string. Don't be fooled by sub-strings,
		etc. */
	start = extensions;
	for (;;)
	{
		where = (GLubyte *) strstr((const char *) start, name);
		if (!where)
			break;
		terminator = where + strlen(name);
		if (where == start || *(where - 1) == ' ')
			if (*terminator == ' ' || *terminator == '\0') {
				return true;
			}
		start = terminator;
	}
	return false;

}
示例#4
0
void *extgl_GetProcAddress(const char *name) {
	void *t = (void*)lwjgl_glXGetProcAddressARB((const GLubyte*)name);
	if (t == NULL) {
		t = dlsym(lib_gl_handle, name);
		if (t == NULL) {
			printfDebug("Could not locate symbol %s\n", name);
		}
	}
	return t;
}
示例#5
0
void *extgl_GetProcAddress(const char *name) {
	void *t = wglGetProcAddress(name);
	if (t == NULL)
	{
		t = GetProcAddress(lib_gl_handle, name);
		if (t == NULL)
		{
			printfDebug("Could not locate symbol %s\n", name);
		}
	}
	return t;
}
示例#6
0
void *extgl_GetProcAddress(const char *name) {
    void *t = eglGetProcAddress(name);

    if ( t == NULL ) {
		t = dlsym(lib_gl_handle, name);
		if ( t == NULL )
            printfDebug("Could not locate symbol %s\n", name);
    }

    //if ( t != NULL )
        //printfDebug("Located symbol %s\n", name);

	return t;
}
示例#7
0
/*
 * Register the LWJGL window class.
 * Returns true for success, or false for failure
 */
bool registerWindow(WNDPROC win_proc, LPCTSTR class_name)
{
	WNDCLASS windowClass;
	memset(&windowClass, 0, sizeof(windowClass));
	windowClass.style = CS_OWNDC;
	windowClass.lpfnWndProc = win_proc;
	windowClass.cbClsExtra = 0;
	windowClass.cbWndExtra = 0;
	windowClass.hInstance = dll_handle;
	windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	windowClass.hbrBackground = NULL;
	windowClass.lpszMenuName = NULL;
	windowClass.lpszClassName = class_name;

	if (RegisterClass(&windowClass) == 0) {
		printfDebug("Failed to register window class\n");
		return false;
	}
	return true;
}
示例#8
0
///////////////////////////////////////////////////////////////////////////////
/// main routine of the demo code
///
///\param argc Number of arguments
///\param argv Arguments
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]) {
    const char* fmuFilNam;
    char* fmuPat;
    char* tmpPat;
    char* xmlPat;
    char* dllPat;
    
    // define default argument values
    double tEnd = 1.0;
    double h=0.1;
    int loggingOn = 0;
    char csv_separator = ',';  
   
    // parse command line arguments
    if (argc>1) {
        fmuFilNam = argv[1];
        
        if(!strcmp(fmuFilNam, "-h") | !strcmp(fmuFilNam, "--help")) {
          printHelp(argv[0]);
          return 0;
        }

        /*if(!strstr(fmuFilNam,"DoubleInputDoubleOutput.fmu")) {
          printf("Sorry, this demo only works with the FMU file DoubleInputDoubleOutput.fmu");
          return 0;
        }*/
    }
    else {
        printError("No fmu file.\n");
        printHelp(argv[0]);
        exit(EXIT_FAILURE);
    }
    if (argc>2) {
        if (sscanf(argv[2],"%lf", &tEnd) != 1) {
            printfError("The given end time (%s) is not a number.\n", argv[2]);
            exit(EXIT_FAILURE);
        }
    }
    if (argc>3) {
        if (sscanf(argv[3],"%lf", &h) != 1) {
            printfError("The given stepsize (%s) is not a number.\n", argv[3]);
            exit(EXIT_FAILURE);
        }
    }
    if (argc>4) {
        if (sscanf(argv[4],"%d", &loggingOn) != 1 || loggingOn<0 || loggingOn>1) {
            printfError("The given logging flag (%s) is not boolean.\n", argv[4]);
            exit(EXIT_FAILURE);
        }
        if(loggingOn) setDebug();
    }
    if (argc>5) {
        if (strlen(argv[5]) != 1) {
            printfError("The given CSV separator char (%s) is not valid.\n", argv[5]);
            exit(EXIT_FAILURE);
        }
        csv_separator = argv[5][0];
    }
    if (argc>6) {
        printf("warning: Ignoring %d additional arguments: %s ...\n", argc-6, argv[6]);
        printHelp(argv[0]);
    }

    // Get absolute path to FMU, NULL if not found  
    tmpPat = getTmpPath(fmuFilNam, strlen(fmuFilNam)-4);
    if(tmpPat==NULL){
      printError("Cannot allocate temporary path.\n");
      exit(EXIT_FAILURE);
    }

    // Unzip the FMU to the tmpPat directory
    if (unpack(fmuFilNam, tmpPat)) {  
        printfError("Fail to unpack fmu \"%s\".\n", fmuFilNam);
        exit(EXIT_FAILURE);
    }

    printDebug("parse tmpPat\\modelDescription.xml.\n");
    xmlPat = calloc(sizeof(char), strlen(tmpPat) + strlen(XML_FILE) + 1);
    sprintf(xmlPat, "%s%s", tmpPat, XML_FILE);

    // Parse only parses the model description and store in structure fmu.modelDescription
    fmu.modelDescription = parse(xmlPat); 
    free(xmlPat);
    if (!fmu.modelDescription) exit(EXIT_FAILURE);

    // Allocate the memory for dllPat
    dllPat = calloc(sizeof(char), strlen(tmpPat) + strlen(DLL_DIR) 
            + strlen( getModelIdentifier(fmu.modelDescription)) +  strlen(".dll") + 1); 
    sprintf(dllPat,"%s%s%s.dll", tmpPat, DLL_DIR, getModelIdentifier(fmu.modelDescription)); 

    // Load the FMU dll
    if (loadDll(dllPat, &fmu)) exit(EXIT_FAILURE); 
	  printfDebug("Loaded \"%s\"\n", dllPat); 

    free(dllPat);
    free(tmpPat);

    // Run the simulation
    printf("FMU Simulator: run '%s' from t=0..%g with step size h=%g, loggingOn=%d, csv separator='%c'\n", 
            fmuFilNam, tEnd, h, loggingOn, csv_separator);
    if (simulate(&fmu, tEnd, h, loggingOn, csv_separator)){
      printError("Simulation failed.\n");
      exit(EXIT_FAILURE);
    }

    printf("CSV file '%s' written", RESULT_FILE);

    // Release FMU 
    FreeLibrary(fmu.dllHandle);
    freeElement(fmu.modelDescription);
    return EXIT_SUCCESS;
}
示例#9
0
///////////////////////////////////////////////////////////////////////////////
/// Simulate the given FMU using the forward euler method.
/// Time events are processed by reducing step size to exactly hit tNext.
/// State events are checked and fired only at the end of an Euler step. 
/// The simulator may therefore miss state events and fires state events typically too late.
///
///\param fmu FMU.
///\param tEnd Ending time of simulation.
///\param h Tiem step size.
///\param loggingOn Controller for logging.
///\param separator Separator character.
///\return 0 if there is no error occurred.
///////////////////////////////////////////////////////////////////////////////
static int simulate(FMU* fmu, double tEnd, double h, fmiBoolean loggingOn, char separator) {
		
  int i, n;
  fmiBoolean timeEvent, stateEvent, stepEvent;
  double time;  
  ModelDescription* md;            // handle to the parsed XML file        
  const char* guid;                // global unique id of the fmu
  fmiCallbackFunctions callbacks;  // called by the model during simulation
  fmiComponent c;                  // instance of the fmu 
  fmiStatus fmiFlag;               // return code of the fmu functions
  fmiReal t0 = 0;                  // start time
	fmiBoolean toleranceControlled = fmiFalse;
  int nSteps = 0;
  FILE* file;

	fmiValueReference vr;			// add it to get value reference for variables

  //Note: User defined references
  //Begin------------------------------------------------------------------
  fmiValueReference vru[1], vry[1]; // value references for two input and two output variables 
  //End--------------------------------------------------------------------

	ScalarVariable** vars = fmu->modelDescription->modelVariables;		// add it to get variables
	int k;							// add a counter for variables
	fmiReal ru1, ru2, ry, ry1, ry2;	// add real variables for input and output
	fmiInteger ix, iy;				// add integer variables for input and output
	fmiBoolean bx, by;				// add boolean variables for input and output
	fmiString sx, sy;				// Zuo: add string variables for input and output
	fmiStatus status;				// Zuo: add stauus for fmi

	printDebug("Instantiate the fmu.\n");		
  // instantiate the fmu
  md = fmu->modelDescription;
  guid = getString(md, att_guid);
	printfDebug("Got GUID = %s!\n", guid);	
  callbacks.logger = fmuLogger;
  callbacks.allocateMemory = calloc;
  callbacks.freeMemory = free;
	printDebug("Got callbacks!\n");
	printfDebug("Model Identifer is %s\n", getModelIdentifier(md));
 	c = fmu->instantiateSlave(getModelIdentifier(md), guid, "Model1", "", 10, fmiFalse, fmiFalse, callbacks, loggingOn);
  if (!c) {
    printError("could not instantiate slaves.\n");
    return 1;
  }
  printDebug("Instantiated slaves!\n");	

  // Open result file
  if (!(file=fopen(RESULT_FILE, "w"))) {
    printfError("could not write %s because:\n", RESULT_FILE);
    printfError("    %s\n", strerror(errno));
    return 1;
  }
  printDebug("Open results file!\n");    

  // Set the start time and initialize
  time = t0;

	printDebug("start to initialize fmu!\n");	   
	fmiFlag =  fmu->initializeSlave(c, t0, fmiTrue, tEnd);	
	printDebug("Initialized fmu!\n");
  if (fmiFlag > fmiWarning) {
    printError("could not initialize model");
    return 1;
  }
 
  // Output solution for time t0 
  printDebug("start to outputRow");
  //outputRow(fmu, c, t0, file, separator, TRUE);  // output column names
  //outputRow(fmu, c, t0, file, separator, FALSE); // output initla value of fmu 
  outputdata(t0, file, separator, 0, 0, TRUE);
  
  printDebug("start to getValueReference");
  ///////////////////////////////////////////////////////////////////////////// 
  // Get value references for input and output varibles
  // Note: User needs to specify the name of variables for their own fmus
  //Begin------------------------------------------------------------------
  vru[0] = getValueReference(getVariableByName(md, "Toa"));
  //vru[1] = getValueReference(getVariableByName(md, "u2"));
  vry[0] = getValueReference(getVariableByName(md, "TrmSou"));
  //vry[1] = getValueReference(getVariableByName(md, "y2"));
  //End--------------------------------------------------------------------
  
  printDebug("Enter in simulation loop.\n");	

  // enter the simulation loop
  while (time < tEnd) {
    if (loggingOn) printf("Step %d to t=%.4f\n", nSteps, time);		  

    ///////////////////////////////////////////////////////////////////////////
    // Step 1: get values of output variables	from slaves
    for (k=0; vars[k]; k++) {
	    ScalarVariable* sv = vars[k];
	    if (getAlias(sv)!=enu_noAlias) continue;	
	    if (getCausality(sv) != enu_output) continue; // only get output variable
      vr = getValueReference(sv);

      switch (sv->typeSpec->type){
        case elm_Real:
          fmu->getReal(c, &vr, 1, &ry); 
          break;
        case elm_Integer:
          fmu->getInteger(c, &vr, 1, &iy);  
          break;
        case elm_Boolean:
          fmu->getBoolean(c, &vr, 1, &by);
          break;
        case elm_String:
          fmu->getString(c, &vr, 1, &sy);
          break;
      }


      // Allocate values to cooresponding varibles on master program
      // Note: User needs to specify the output variables for their own fmu 
      //Begin------------------------------------------------------------------
      if (vr == vry[0]) ry1 = ry;
      //else if(vr == vry[1]) ry2 = ry;
      //End--------------------------------------------------------------------
    } 
    
    ///////////////////////////////////////////////////////////////////////////
    // Step 2: compute on master side 
    // Note: User can adjust the computing schemes of mater program
    //Begin------------------------------------------------------------------
     printf("Dymola output = %f\n", ry1);
	 //= ry2 + 3.0; 
    ru1 = 293;
    //End--------------------------------------------------------------------

    //////////////////////////////////////////////////////////////////////////
    // Step 3: set input variables back to slaves
    for (k=0; vars[k]; k++) {
      ScalarVariable* sv = vars[k];
      if (getAlias(sv)!=enu_noAlias) continue;
	    if (getCausality(sv) != enu_input) continue; // only set input variable
        vr = getValueReference(sv);
        // Note: User can adjust the settings for input variables
        //Begin------------------------------------------------------------------
        switch (sv->typeSpec->type){
          case elm_Real:

            if(vr == vru[0]) {
              fmu->setReal(c, &vr, 1, &ru1); 				
              printDebug("Set u1.\n");
            }
            //else if (vr == vru[1]) {
            //  fmu->setReal(c, &vr, 1, &ru2);
            //  printDebug("Set u2.\n");
            //}
            else
              printf("Warning: no data given for input variable.\n");
            break;
          case elm_Integer:
            fmu->setInteger(c, &vr, 1, &ix);  
            break;
          case elm_Boolean:
            fmu->setBoolean(c, &vr, 1, &bx);
            break;
          case elm_String:
		    printDebug("Get string in simulatio()");
            fmu->setString(c, &vr, 1, &sx);
            break;        
        }
        //End--------------------------------------------------------------------        
    } 
    
    // Advance to next time step
    status = fmu->doStep(c, time, h, fmiTrue);  
    // Terminate this row
    // fprintf(file, "\n");  (comment out this line to get rid of the blank line between the results in the csv file.)    
   
    time = min(time+h, tEnd);
    //outputRow(fmu, c, time, file, separator, FALSE); // output values for this step
	outputdata(time, file, separator, ru1, ry1, FALSE);
    nSteps++;
   
  } // end of while  

  // Cleanup
  fclose(file);

  // Print simulation summary 
  if (loggingOn) printf("Step %d to t=%.4f\n", nSteps, time);		
  printf("Simulation from %g to %g terminated successful\n", t0, tEnd);
  printf("  steps ............ %d\n", nSteps);
  printf("  fixed step size .. %g\n", h);

  return 0; // success
}
示例#10
0
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Pop the children from the stack and check for correct type and sequence of children
/// This is the end handler of parser. The parser ends here.
///
///\param context
///\param elm 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void XMLCALL endElement(void *context, const char *elm) {
    Elm el;
    el = checkElement(elm);
    printfDebug(" **** ending element %s.\n", elmNames[el]);
    switch(el) {        
        case elm_fmiModelDescription: 
            {
                 ModelDescription* md;
                 ListElement** im = NULL;  		//  NULL or list of CoSimulation_StandAlone under Implementation
                 ListElement** ud = NULL;     	//  NULL or list of BaseUnits under UnitDefinitions
                 Type**        td = NULL;     	//  NULL or list of Types under TypeDefinitions
                 Element*      de = NULL;     	// NULL or DefaultExperiment
                 ListElement** va = NULL;     	// NULL or list of Tools
                 ScalarVariable** mv = NULL;  	// NULL or list of ScalarVariables under ModelVariables
                 ListElement* child;
                 printDebug("$$$$$ entered endElement 'elm_fmiModelDescription'\n");
                 child = checkPop(ANY_TYPE); // get a child from stack

                 while (child && child->type != elm_fmiModelDescription)  // add while-loop in case the elements in the random order
                 {
					 if (child->type == elm_VendorAnnotations){
						 va = (ListElement**)child->list;    // VendorAnnotations (ListElement) contains Tool (ListElement))
						 free(child);
						 child = checkPop(ANY_TYPE);
						 if (!child) return;
					 }
					 if (child->type == elm_DefaultExperiment){
						 de = (Element*)child;				// DefaultExperiment (Element) with only attributes
						 child = checkPop(ANY_TYPE);
						 if (!child) return;
					 }
					 if (child->type == elm_TypeDefinitions){
						 td = (Type**)child->list;     		// TypeDefinitions (ListElement) contains Type (Type)
						 free(child);
						 child = checkPop(ANY_TYPE);
						 if (!child) return;
					 }
					 if (child->type == elm_UnitDefinitions){
						 ud = (ListElement**)child->list;   // UnitDefinitions (ListElement) contains BaseUnit (ListElement)
						 free(child);
						 child = checkPop(ANY_TYPE);
						 if (!child) return;
					 }
					 if (child->type == elm_Implementation){ 	// Implementation is listElement, it can be treated the same as UnitDefinitions
						 im = (ListElement**)child->list; 		// Implementation (Implementation) contains CoSimulation_StandAlone (ListElement)
						 free(child);							// Zuo:
						 child = checkPop(ANY_TYPE);			// Zuo:
						 if (!child) return;					// Zuo:
					 }											// Zuo:
					 if (child->type == elm_ModelVariables){
						  mv = (ScalarVariable**)child->list;  // ModelVariables (ListElement) contains ScalarVariable (ScalarVariable)
						  free(child);
						  child = checkPop(ANY_TYPE);
						  if (!child) return;
					 }
                 }
		         printDebug("$$$$$ checking element type \n");
                 if (checkElementType(child, elm_fmiModelDescription)) return;
                 printDebug("$$$$$ checked  element type \n");
                 md = (ModelDescription*)child;

                 // the following build the link of elements for ModelDescriptions
                 md->modelVariables = mv;
                 md->implementation = im; // added M. Wetter
                 md->vendorAnnotations = va;
                 md->defaultExperiment = de;
                 md->typeDefinitions = td;
                 md->unitDefinitions = ud;
                 printDebug("$$$$$ calling stackPush \n");
                 stackPush(stack, md);
                 printDebug("$$$$$ called stackPush \n");
                 break;
            }
        case elm_Type:
            {
                Type* tp;
                Element* ts = checkPop(ANY_TYPE);
                if (!ts) return;  // If there is no sub-element, return
                if (checkPeek(elm_Type)) return; // If the sub-element is not Type, return
                tp = (Type*)stackPeek(stack);  // Get the element
                switch (ts->type) {
                    case elm_RealType:
                    case elm_IntegerType:
                    case elm_BooleanType:
                    case elm_EnumerationType:
                    case elm_StringType:
                        break;
                    default: 		// Element type does not match
                         logFatalTypeError("RealType or similar", ts->type);
                         return;
                }
                tp->typeSpec = ts;  	// parent (tp) links to sub-element (ts)
                break;
            }
        case elm_ScalarVariable:
            {
                ScalarVariable* sv;
                Element** list = NULL;
                Element* child = checkPop(ANY_TYPE);
                if (!child) return;
                if (child->type==elm_DirectDependency){
                    list = ((ListElement*)child)->list; // DirectDependency is ListElement
                    free(child);
                    child = checkPop(ANY_TYPE);
                    if (!child) return;
                }
                if (checkPeek(elm_ScalarVariable)) return;  // If next element is not ScalarVariable, return
                sv = (ScalarVariable*)stackPeek(stack);
                switch (child->type) {
                    case elm_Real:
                    case elm_Integer:
                    case elm_Boolean:
                    case elm_Enumeration:
                    case elm_String:
                        break;
                    default:
                         logFatalTypeError("Real or similar", child->type);
                         return;
                }
                sv->directDependencies = list;
                sv->typeSpec = child;
                break;
            }
        case elm_Implementation:  	popList(elm_CoSimulation_StandAlone); break; // Needs to be modified if CoSimulation_Tool is added
	    case elm_CoSimulation_StandAlone:  popList(elm_Capabilities); break; // CoSimulation_StandAlone only has Capabilities
        case elm_ModelVariables:    popList(elm_ScalarVariable); break;
        case elm_VendorAnnotations: popList(elm_Tool);break;
        case elm_Tool:              popList(elm_Annotation); break;
        case elm_TypeDefinitions:   popList(elm_Type); break;
        case elm_EnumerationType:   popList(elm_Item); break;
        case elm_UnitDefinitions:   popList(elm_BaseUnit); break;
        case elm_BaseUnit:          popList(elm_DisplayUnitDefinition); break;
        case elm_DirectDependency:  popList(elm_Name); break;
        case elm_Name:
            {
                 // Exception: the name value is represented as element content.
                 // All other values of the XML file are represented using attributes.
                 Element* name = checkPop(elm_Name);
                 if (!name) return;
                 name->n = 2;
                 name->attributes = malloc(2*sizeof(char*));
                 name->attributes[0] = attNames[att_input];
                 name->attributes[1] = data;
                 data = NULL;
                 skipData = 1; // stop recording element content
                 stackPush(stack, name);
                 break;
            }
        case -1: return; // illegal element error
        default: // must be a leaf Element
				printDebug("+++++++ got a leaf element\n");
                assert(getAstNodeType(el)==astElement);
                break;
    }
    // All children of el removed from the stack.
    // The top element must be of type el now.
    checkPeek(el);
}