Пример #1
0
/* the functions frees the allocated memory */
void garbage_collect(void){
  if(synerrno)
    printf("\nSyntax errors: %d\n",synerrno);
  printf("\nCollecting garbage...\n");
  b_destroy(sc_buf);
  b_destroy(str_LTBL);  
  st_destroy(sym_table);
}
Пример #2
0
/**********************************************************************************************************
Purpose:				Set the Token code and attribute for a keyword or arithmetic variable identifier
Author:					Chris Whitten modified by Thom Palmer
History/Versions:		10.19.13
Called functions:		iskeyword(), strlen()
Parameters:				char lexeme[]
Return value:			Token t representing a valid keyword or valid arithmetic variable identifier
Algorithm:				Create a temporary Token, if lexeme is a keyword set appropriate properties of 
						the Token and return the keyword Token, otherwise lexeme is an arithmetic variable
						identifier, set appropriate properties and return the Token
						* Assume that size_t is that same size as an int *
**********************************************************************************************************/
Token aa_func02(char lexeme[])
{
	Token t;			/* Temporary Token */
	int kwIndex;		/* Stores index in kw_table */
	int vid_offset;     /* Temporarily stores offset where vid was installed */
	
	
	/* Call iskeyword to find if lexeme is a keyword */
	kwIndex = iskeyword(lexeme);
	if( kwIndex >=0)
	{
		/* lexeme is a keyword. Set token code and attribute. */
		t.code = KW_T;
		t.attribute.kwt_idx = kwIndex;
		return t;
	}
	/* lexeme is an arithmetic variable identifier. Set appropriate code. */
	t.code = AVID_T;
	/* If lexeme is longer than VID_LEN add string terminator in lexeme at VID_LEN index */
	if (strlen(lexeme) > VID_LEN)		
	{
		lexeme[VID_LEN] = STRTERM;
	}
	/* Iterate until the end of the  lexeme and add lexeme characters to vid_lex */
	vid_offset = st_install(sym_table,lexeme, line);
	if(vid_offset < 0 )
	{
		printf("\nError: The Symbol Table is full - install failed.\n");
		st_store(sym_table);
		b_destroy(lex_buf);
		exit(SYM_TBL_FULL);
	}
	t.attribute.vid_offset = vid_offset;
	return t;
}
Пример #3
0
/*******************************************************************************
* Purpose:			Frees memory occupied by symbol table dynamic areas and sets
*					global symbol table size to 0.
* Author:			Skye Turriff
* History:			Version 1, 21 November 2015
* Called functions:	b_destroy(), free(), st_setsize()
* Parameters:		STD sym_table struct
* Return value:		None
*******************************************************************************/
void st_destroy(STD sym_table) {
	if (sym_table.st_size != 0) {
		b_destroy(sym_table.plsBD);
		free(sym_table.pstvr);
		st_setsize();
	}
}
Пример #4
0
/*
Purpose: Frees the memory occupied by the symbol table 
		dynamic areas and sets st_size to 0.
Author: Kwok Hong Kelvin Chan
Version: 13.11.14
Called functions: free(), b_destroy()
Parameters: STD sym_table
Return value: void
*/
void st_destroy(STD sym_table) {
	/* check if the symbol table is valid */
	if (sym_table.st_size > 0) {
		free(sym_table.pstvr); /* free the STVR array allocated memory */
		b_destroy(sym_table.plsBD); /* free the Buffer allocated memory by calling b_destroy() */
		sym_table.st_size = 0; /* reset symbol table st_size */
	}
}
Пример #5
0
/********************************************************************
Function name:      st_destroy()
Purpose:            This function frees the memory occupied by the symbol table dynamic areas and sets st_size to 0. 
Author:             Warren Rainey
History/Versions:   1.0
Called functions:   b_destroy(), free(), st_setsize()
In parameters:      STD
Return Value:       Void
**********************************************************************/  
void st_destroy(STD sym_table){
	if(sym_table.plsBD==NULL && sym_table.pstvr == NULL){
		return;
	}
	if(sym_table.st_size != 0){
		b_destroy(sym_table.plsBD);
		free(sym_table.pstvr);
		st_setsize();/*Set size of symboltable to 0*/
	}
	return;
}
Пример #6
0
/* create a disk writer worker thread
 * main loop for the disk writer worker process */
void *disk_writer_thread(void *arg) {
    disk_writer_t *self = (disk_writer_t *)arg;

    queue_t private_queue;
    queue_t *main_queue = &self->queue;
    blob_t *b;
    uint32_t done_work= 0;
    
    recreate_fallback_path(self->fallback_path);
    SAY("disk writer started using path '%s' for files", self->fallback_path);

    memset(&private_queue, 0, sizeof(private_queue));

    while( 1 ){

        q_hijack(main_queue, &private_queue, &POOL.lock);
        b= private_queue.head;

        if ( b == NULL ) {
            if (done_work) {
                SAY("cleared disk queue of %d items", done_work);
                done_work= 0;
            }

            setup_for_epoch(self, 0);
            if (RELAY_ATOMIC_READ(self->exit)) {
                /* nothing to do and we have been asked to exit, so break from the loop */
                break;
            }
            else {
                w_wait( CONFIG.polling_interval_ms );
            }
        } else {
            do {
                done_work++;
                write_blob_to_disk(self, b);
                b_destroy( q_shift_nolock( &private_queue) );
            } while ((b = private_queue.head) != NULL);

            (void)snapshot_stats( self->pcounters, self->ptotals );
        }
    }

    (void)snapshot_stats( self->pcounters, self->ptotals );

    SAY("disk_writer saved " STATSfmt " packets in its lifetime", self->ptotals->disk_count);

    return NULL;
}
Пример #7
0
/**********************************************************************************************************
Purpose:				Free all the dynamically allocated memory associated with the symbol table. 
Author:					Thom Palmer
History/Versions:		10.18.13
Called functions:		b_destroy(), free()
Parameters:				STD sym_table
Return value:			void
Algorithm:				Check to ensure both dynamically allocated structures have valid pointers before 
						freeing the memory. We thought this was safer then checking the size.
**********************************************************************************************************/
void st_destroy(STD sym_table)
{
	/* Even though b_destroy handles NULL this check avoids creating an unnecessary stack frame */
	if(sym_table.plsBD)
	{
		b_destroy(sym_table.plsBD);
	}
	/* Ensure the pointer is valid before freeing the memory to avoid crashing */
	if(sym_table.pstvr)
	{
		free((STVR*)sym_table.pstvr);		
	}
	/* Set the size to 0 so the STD will be marked as invalid */
	st_setsize();
}
Пример #8
0
/**********************************************************************************************************
Purpose:				Set the Token code and attribute for a string variable identifier
Author:					Chris Whitten
History/Versions:		10.19.13
Called functions:		strlen()
Parameters:				char lexeme[]
Return value:			Token t representing a valid string variable identifier
Algorithm:				Create a temporary Token, Assign a SVID_T code to the Token, Copy the SVID to the
						vid_lex array up to 8 characters and ensure that end of string is added to the
						array. Return the token.
						* Assume that size_t is that same size as an int *
**********************************************************************************************************/
Token aa_func03(char lexeme[])
{
	Token t;			/* Temporary Token */
	int vid_offset;     /* Temporarily stores offset where vid was installed */

	/* lexeme is an string variable identifier. Set appropriate code. */
	t.code = SVID_T;
	/* If lexeme is longer than VID_LEN add string terminator in lexeme at VID_LEN and # at VID_LEN-1*/
	if (strlen(lexeme) > VID_LEN)		
	{
		lexeme[VID_LEN-1] = '#';
		lexeme[VID_LEN] = STRTERM;
	}
	vid_offset = st_install(sym_table,lexeme, line);
	if(vid_offset < 0)
	{
		printf("\nError: The Symbol Table is full - install failed.\n");
		st_store(sym_table);
		b_destroy(lex_buf);
		exit(SYM_TBL_FULL);
	}
	t.attribute.vid_offset = vid_offset;
	return t;
}
Пример #9
0
/**********************************************************************************************************
Purpose:			Set the proper token depending on the lexeme read from the buffer. 
Author:				Thom Palmer and Chris Whitten
History/Versions:	10.20.13
Called functions:	b_setmark(), b_getc(), b_getmark(), SEOF(), WHTSPACE(), is_assop(), strncmp(),
					b_set_getc_offset(), b_retract(), b_get_getc_offset(),b_eob(), isalnum(), b_addc()
					get_next_state(), b_create(), b_pack(), b_destroy() 
Parameters:			Buffer * const pBD
Return value:		Token t
Algorithm:			Validate parameters, read char from buffer, check the char to see if its a legal character.
					depending on the char peak forward to see what the following char is in order to 
					determine if it's part of the lexeme or if it's time to return. once a valid lexeme is
					found set the token and return. if a valid lexeme is not found set the token to error 
					state and return. 
**********************************************************************************************************/
Token mlwpar_next_token(Buffer * sc_buf)
{
	Token t;			/* token to return after recognition */
	unsigned char c;	/* input symbol */
	int state = 0;		/* initial state of the FSM */
	unsigned int retrCtr;
	short lexstart;		/* start offset of a lexeme in the input buffer */
	short lexend;		/* end offset of a lexeme in the input buffer */
	int accept = NOAS;	/* type of state - initially not accepting */  
	unsigned int i=0;	/* Used throughout the function as iterator */
   
	/* Ensure the buffer is not null before trying to access it */

	if(sc_buf == NULL)
	{	   
		scerrnum = BUFFNULL;  
	     t_set_err_t(RUNTIMERR, t);
	}     
                
	while (1) /* Endless loop broken by token returns it will generate a warning */
	{ 
                
		/* Set mark before getting the next character. This prevents the need for unneccessary decrements. */
		b_setmark(sc_buf, b_get_getc_offset(sc_buf));
		lexstart = b_getmark(sc_buf);
	
		/* Get the next char from the buffer. */
		c = b_getc(sc_buf); 	
	
		/* Ensure SEOF has not been read before processing any further. */
		if(SEOF(c))
		{
			t.code = SEOF_T;
			return t;
		}

		/* If it's whitespace ignore and return to the start of the loop. */
		if(WHTSPC(c))
		{
			continue;
		}

		/* Drop into switch statement to determine what the character can potentially represent and handle it appropriatly. */
		switch(c)
		{
			/* If c is '=' the token can either be a relation operatory or an assignment operator,  so peak forward */
			case EQSIGN:
				{ 
					c = b_getc(sc_buf);
					/* If the next character is '=' then we have found a relational operator */
					if(c == EQSIGN) 
					{
						/* Set the code and attribute and return t */
						t.code = REL_OP_T;
						t.attribute.rel_op = EQ;
						return t;
					}
					/* Otherwise retract and return an assignment operator token */
					b_retract(sc_buf);
					t.code = ASS_OP_T;
					return t;
				} 
			/* If the token starts with ! it can either be a comment or the != relational operator, so peak forward and act appropriatly. */
			case EXCLAMTN:
				c = b_getc(sc_buf);
				/* If the next token is < then we have a comment therfore ignore everything in the line.*/
				if(c == LESSTHN)
				{
					do
					{
						c = b_getc(sc_buf);
						if(SEOF(c))
						{ 
							t.code = ERR_T;
							t.attribute.err_lex[0] = EXCLAMTN;
							t.attribute.err_lex[1] = LESSTHN;
							t.attribute.err_lex[2] = c;
							t.attribute.err_lex[3] = STRTERM;
							b_retract(sc_buf);
							return t;
						}
					}while ( c != NEWLINE && c != CARRTRN);

					++line;
					continue;
				}
				/* If the next token we have the NE relational operator. */
				if(c == EQSIGN)
				{
					t.code = REL_OP_T;
					t.attribute.rel_op = NE ;
					return t;
				}
				/* if the next char is neither = or < we have an error set ERR_T*/
				t.code = ERR_T;
				t.attribute.err_lex[0] = EXCLAMTN;
				t.attribute.err_lex[1] = c;
				t.attribute.err_lex[2] = STRTERM;
	   
				/* We assume the error was meant to be a token so ignore everything in the line. */
				do
				{
					c = b_getc(sc_buf);
					/* If SEOF or b_eob is found retract the buffer and return t */
					if(SEOF(c))
					{
						b_retract(sc_buf);
						return t;
					}
				}while ( c != NEWLINE);
				++line;
				return t;

			/*If we have a plus sign '+' set the token and it's attirbute then return. */
			case POS:
				t.code = ART_OP_T;
				t.attribute.arr_op = PLUS;
				return t;

			/*If we have a minus sign '-' set the token and it's attirbute then return. */
			case NEG:
				t.code = ART_OP_T;
				t.attribute.arr_op = MINUS;
				return t;

			/*If we have a a period '.' it could be a logical operator or an error. */
			case PERIOD:
				retrCtr = 1;
				i = 0;
				c = b_getc(sc_buf);
				
				/* Switch on the first character read after the period '.' */
				switch (c) 
				{
				/* If its an 'A' we might have .AND. */
				case'A' :
					/* Compare the string the string read from the buffer to the string literal .AND.  */
					++retrCtr;
					if(b_getc(sc_buf) == 'N')
					{
						++retrCtr;
						if(b_getc(sc_buf) == 'D')
						{
							++retrCtr;
							if(b_getc(sc_buf) == PERIOD)
							{
								t.code = LOG_OP_T;
								t.attribute.log_op = AND;
								return t;
							}
						}
					}
					break;
				case'O':
					/* Comapre the string the string read from the buffer to the string literal .OR.  */
					++retrCtr;
					if(b_getc(sc_buf) == 'R')
					{
						++retrCtr;
						if(b_getc(sc_buf) == PERIOD)
						{
							t.code = LOG_OP_T;
							t.attribute.log_op = OR;
							return t;
						}
					}

					break;
				}

				while(i<retrCtr)
				{
					b_retract(sc_buf);
					i++;
				}
				t.code = ERR_T;
				/* Add char which caused the error to the err_lex */
				t.attribute.err_lex[0] = PERIOD;
				t.attribute.err_lex[1] = STRTERM;
				return t;

			/* If we have an astrix sign '*' set the token and it's attirbute then return. */
			case ASTRX:
				t.code = ART_OP_T;
				t.attribute.arr_op = MULT;
				return t;

			/* If c is a forward slash '/' set the token and it's attirbute then return. */
			case FWDSLSH:
				t.code = ART_OP_T;
				t.attribute.arr_op = DIV;
				return t;

			/* If c is a left brace '{' set the token and it's attirbute then return. */
			case LBRACE:
				t.code = LBR_T;
				return t;

			/* If c is a right brace '}' set the token and it's attirbute then return. */
			case RBRACE:
				t.code = RBR_T;
				return t;

			/* If c is a left parenthesis '(' set the token and it's attirbute then return. */
			case LPRNTHS:
				t.code = LPR_T;
				return t;

			/* If c is a right parenthesis ')' set the token and it's attirbute then return. */
			case RPRNTHS:
				t.code = RPR_T;
				return t;

			/* If c is a less than symbol '<' check the next char. */
			case LESSTHN:
				c = b_getc(sc_buf);

				/* If the next char is the greater than symbol '>' set the proper token and return. */
				if(c == GRTRTHN){
					t.code = SCC_OP_T;
					return t;
				}

				/* If the next char is not recognized restract the buffer and set the token */
				t.code = REL_OP_T;
				t.attribute.rel_op = LT;
				b_retract(sc_buf);
				return t;

			/* If c is a greater than symbol '>' set the proper token and return. */
			case GRTRTHN:
				t.code = REL_OP_T;
				t.attribute.rel_op = GT;
				return t;

			/* If c is a new line '\n' increment the line number and return to the start of the loop. */
			case CARRTRN:
				NEWLINE_TEST
				continue;
				
			/* If c is a NEWLINE character increment the line number and continue */
			case NEWLINE:
				++line;
				continue;

			/* If c is a comma ',' set the proper token and return. */
			case COMMA:
				t.code = COM_T;  
				return t;

			/* If c is a semi colon ';' set the proper token and return. */
			case SEMICLN:
				t.code = EOS_T;
				return t;

			/* If c is a quotation mark '"' we have the start of a string, analyze the next chars until '"' or SEOF is hit. */
			case QUOTE:
				/* read all the chars in from the input buffer until a '"' */
				do
				{
					c = b_getc(sc_buf);
					lexend = b_get_getc_offset(sc_buf);
					/* If eob has be set or SEOF is read in from the buffer prior to closing the string */
					/* Break into the error token setup. */
					if( SEOF(c))
					{	
						/* Set the getc_offset to the start of the string */
						b_set_getc_offset(sc_buf,lexstart);
						/* Iterate over the buffer and copy the contents of the error string into the err_lex */
						for( i = 0; i < lexend-lexstart; i++) /* Comparison of unsigned int and short will generate warning. 
															     lexend-lexstart will always be positive no need to cast */
						{				
							c = b_getc(sc_buf);
							/* For the first 20 characters */
							if(i<=ERR_LEN)
							{
								/* Copy c into the current index of err_lex for first 16 characters */
								if(i<=16)
								t.attribute.err_lex[i] = c;
								/* Copy a decimal into the indexes between 17 and ERR_LEN */
								if(i>16 && i<ERR_LEN)
								{
									t.attribute.err_lex[i] = PERIOD;
								}
								/* Copy a string terminator into the last index of err_lex */
								if (i==ERR_LEN)
								{
									t.attribute.err_lex[i]= STRTERM;
								}

							}
					
						}
						t.code = ERR_T;							
						return t;
					}
					/* Increment the line number each time a line terminator is found */
					if(c == NEWLINE)
					{
						++line;
					}
					if(c == CARRTRN)
					{
						NEWLINE_TEST
					}
				}while ( c != QUOTE );
			
				/* Closing quote found. Valid String */
				/* Set the getc_offset back to the start of the string */
				b_set_getc_offset(sc_buf,lexstart);
				/* Set the str_offset attribute to the location of the current getc_offset in the str_LTBL */
				t.attribute.str_offset = b_getsize(str_LTBL);

				/* Add the characters of the string into the str_LTBL */
				for(  i = 0; i< lexend-lexstart;i++) /* Comparison of unsigned int and short will generate warning. 
														lexend-lexstart will always be positive no need to cast */
				{			
					c = b_getc(sc_buf);
					/* Ensure that quotes are not added to the string */
					if(c != '"')
					{
						if(!b_addc(str_LTBL, c))
						{
							scerrnum = FAILADDC;
							t_set_err_t(RUNTIMERR, t);
						}
					}
				}
				/* Add the string terminator to the string and set the Token Code */
				if (!b_addc(str_LTBL,STRTERM))
				{
					scerrnum = FAILADDC;
					t_set_err_t(RUNTIMERR, t);
				}
				t.code = STR_T;
				return t;
			}
	
		/* Special symbol scanning completed. Now checking for lexeme type */
		if (isalnum(c))
		{
			/* Use for loop to iterate over the transition table based on the current state and character */
			/* Continue iterating until an accepting state has been found */
			for(state = get_next_state(state,c,&accept);accept==NOAS; state = get_next_state(state,c,&accept))
			{
				c = b_getc(sc_buf);
			}
		
			/* Retract the buffer if is is an accepting state with a retract */
			if(accept==ASWR)
			{
				b_retract(sc_buf);
			}
			/* Set the end of the lexeme at the current getc_offset */
			lexend = b_get_getc_offset(sc_buf);
			/* Create a temporary buffer to store the lexeme */
			lex_buf = b_create((lexend - lexstart +1),0,'f');
			/* If buffer creation was not successful. Set the error token for a runtime error. */
			if (!lex_buf)
			{
				scerrnum = BUFFNULL;
				t_set_err_t(RUNTIMERR, t);
			}

			
			
			/* Reset the getc_offset to the start of the lexeme */
			b_set_getc_offset(sc_buf,lexstart);
			/* Add the characters of the lexeme to lex_buf */
			for( i = 0;i<lexend-lexstart;i++) /* Comparison of unsigned int and short will generate warning. 
												 lexend-lexstart will always be positive no need to cast */
			{
				if (!b_addc(lex_buf,b_getc(sc_buf)))
				{
					scerrnum = FAILADDC;
					t_set_err_t(RUNTIMERR, t);
				}
			}
			/* Pack lex_buf and add the string terminator to it */
			b_pack(lex_buf);
			/* If b_addc fails set the token for a runtime error and return t  */
			if (!b_addc(lex_buf,STRTERM))
			{
				scerrnum = FAILADDC;
				t_set_err_t(RUNTIMERR, t);
			}
			/* Call the accepting function at the current state index and pass the lexeme */
			t = aa_table[state](b_get_chmemloc(lex_buf,0));
			b_destroy(lex_buf);
			return t;
		}
		/* This code will be executed if c was an invalid symbol*/
		/* Set error token and return t. */
		t.code = ERR_T;
		t.attribute.err_lex[0] = c;
		t.attribute.err_lex[1] = STRTERM; /*Probably a better way to do this.*/
		return t;             
   }
}
Пример #10
0
int main(int argc, char **argv){

	Buffer *ptr_Buffer;   /* pointer to Buffer structure */
	FILE *fi;             /* input file handle */
	int loadsize = 0;     /*the size of the file loaded in the buffer */
	int ansi_c = !ANSI_C; /* ANSI C compliancy flag */

	/* Check if the compiler option is set to compile ANSI C */
	/* __DATE__, __TIME__, __LINE__, __FILE__, __STDC__ are predefined preprocessor macros*/
	if (ansi_c){
		err_printf("Date: %s  Time: %s", __DATE__, __TIME__);
		err_printf("ERROR: Compiler is not ANSI C compliant!\n");
		exit(1);
	}

	/* missing file name or/and mode parameter */
	if (argc <= 2){

		err_printf("\nDate: %s  Time: %s", __DATE__, __TIME__);
		err_printf("\nRuntime error at line %d in file %s\n", __LINE__, __FILE__);
		err_printf("%s\b\b\b\b%s%s", argv[0], ": ", "Missing parameters.");
		err_printf("Usage: platybt source_file_name mode");
		exit(1);
	}

	/* create a source code input buffer */
	switch (*argv[2]){ /*gets the first caracter of the mode argument*/
	case 'f': case 'a': case 'm': break;
	default:
		err_printf("%s%s%s", argv[0], ": ", "Wrong mode parameter.");
		exit(1);
	}
	/*create the input buffer */
	ptr_Buffer = b_create(INIT_CAPACITY, INC_FACTOR, *argv[2]);
	if (ptr_Buffer == NULL){
		err_printf("%s%s%s", argv[0], ": ", "Could not create buffer.");
		exit(1);
	}

	/* open the source file */
	if ((fi = fopen(argv[1], "r")) == NULL){
		err_printf("%s%s%s%s", argv[0], ": ", "Cannot open file: ", argv[1]);
		exit(1);
	}

	/* load a source file into the input buffer  */
	printf("Reading file %s ....Please wait\n", argv[1]);
	loadsize = b_load(fi, ptr_Buffer);
	if (loadsize == R_FAIL_1)
		err_printf("%s%s%s", argv[0], ": ", "Error in loading buffer.");

	/* close the source file */
	fclose(fi);
	/*find the size of the file  */
	if (loadsize == LOAD_FAIL){
		printf("The input file %s %s\n", argv[1], "is not completely loaded.");
		printf("Input file size: %ld\n", get_filesize(argv[1]));
	}
	/* set a mark at the last char in the buffer*/
	b_setmark(ptr_Buffer, b_size(ptr_Buffer));

	/* display the contents of the input buffer */
	display(ptr_Buffer);

	/* pack the buffer
	* if possible, add end-of-file character (EOF) to the buffer
	* display again
	*/
	if (b_pack(ptr_Buffer)){
		if (!b_addc(ptr_Buffer, EOF))
			err_printf("%s%s%s", argv[0], ": ", "Error in writing to buffer.");
		display(ptr_Buffer);
	}


	/* destroy the buffer */
	b_destroy(ptr_Buffer);
	/* make the buffer invalid
	It is not necessary here because the function terminates anyway,
	but will prevent run-time errors and crashes in future expansions
	*/
	ptr_Buffer = NULL;
	/*return success */
	return (0);
}
Пример #11
0
/*  main function takes a PLATYPUS source file as
 *  an argument at the command line.
 *  usage: scanner source_file_name"
 */     
int main(int argc, char ** argv){

	Buffer *sc_buf; /* pointer to input (source) buffer */
	FILE *fi;       /* input file handle */
	Token t;        /* token produced by the scanner */
	int loadsize = 0; /*the size of the file loaded in the buffer */
    int ansi_c = !ANSI_C; /* ANSI C compliancy flag */

/* Check if the compiler option is set to compile ANSI C */
/* __DATE__, __TIME__, __LINE__, __FILE__, __STDC__ are predefined preprocessor macros*/
  if(ansi_c){
    err_printf("Date: %s  Time: %s",__DATE__, __TIME__);
    err_printf("ERROR: Compiler is not ANSI C compliant!\n");
    exit(1);
  }

/*check for correct arrguments - source file name */
      if (argc <= 1){
/* __DATE__, __TIME__, __LINE__, __FILE__ are predefined preprocessor macros*/
       err_printf("Date: %s  Time: %s",__DATE__, __TIME__);
       err_printf("Runtime error at line %d in file %s", __LINE__, __FILE__);
       err_printf("%s%s%s",argv[0],": ","Missing source file name.");
       err_printf("%s%s%s","Usage: ", "scanner", "  source_file_name");
       exit(1);
	}	
 

 /* create a source code input buffer - multiplicative mode */	
	sc_buf = b_create(INIT_CAPACITY,INC_FACTOR,'m');
	if (sc_buf == NULL){
	  err_printf("%s%s%s",argv[0],": ","Could not create source buffer");
	  exit(1);
	}

/*open source file */
	if ((fi = fopen(argv[1],"r")) == NULL){
		err_printf("%s%s%s%s",argv[0],": ", "Cannot open file: ",argv[1]);
		exit (1);
	}
/* load source file into input buffer  */
     printf("Reading file %s ....Please wait\n",argv[1]);
     loadsize = b_load (fi,sc_buf);
     if(loadsize == R_FAIL_1)
       err_printf("%s%s%s",argv[0],": ","Error in loading buffer.");

/* close source file */	
 	fclose(fi);
/*find the size of the file  */
    if (loadsize == LOAD_FAIL){
     printf("The input file %s %s\n", argv[1],"is not completely loaded.");
     printf("Input file size: %ld\n", get_filesize(argv[1]));
    }
/* pack and display the source buffer */

       if(b_pack(sc_buf)){
         display(sc_buf);
  }

/* create string Literal Table */
 	
  str_LTBL = b_create(INIT_CAPACITY,INC_FACTOR,'a');
	if (str_LTBL == NULL){
	 err_printf("%s%s%s",argv[0],": ","Could not create string literals buffer");
	 exit(1);
	}
	
	/*Testbed for the scanner */
/* add SEOF to input program buffer*/
	b_addc(sc_buf,'\0');

	/* Initialize scanner input buffer */ 
	if(scanner_init(sc_buf)){;
	  err_printf("%s%s%s",argv[0],": ","Empty program buffer - scanning canceled");
	  exit(1); 
	}	

	printf("\nScanning source file...\n\n");
	printf("Token\t\tAttribute\n");
	printf("----------------------------------\n");
	do{	
	  t= mlwpar_next_token(sc_buf);  
	  print_token(t);
	}while(t.code != SEOF_T);
  if(b_size(str_LTBL)) b_print(str_LTBL);
	b_destroy(sc_buf);
	b_destroy(str_LTBL);
	sc_buf = str_LTBL = NULL;
 
  return (0);
}
Пример #12
0
/* The function frees all dynamically allocated memory. 
   This function is always called
   despite how the program terminates - normally or abnormally. 
*/
void garbage_collect(void){
  printf("\nCollecting garbage...\n");
	b_destroy(sc_buf);
	b_destroy(str_LTBL);  
	st_destroy(sym_table);
}
Пример #13
0
Token malpar_next_token(Buffer * sc_buf)
{
		Token t;         /*token to be returned */
		unsigned char c; /* input symbol */
		Buffer *lex_buf; /* temporary buffer for holding lexemes */       
		int accept = NOAS; /* Not Accepting State */
		int state = 0;     /* Start state in the Transition Table */
		int lexstart;      /* current lexeme start offset */ 
 static int forward;  /* current input char offset */                                       
/* 
forward is the offset from the beginning of the char buffer of the
input buffer (sc_buf) to the current character, which is to be processed
by the scanner.
lexstart is the offset from the beginning of the char buffer of the
input buffer (sc_buf) to the first character of the current lexeme,
which is being processed by the scanner.
*/ 
		
		
	   /* DECLARE YOUR VARIABLES HERE IF NEEDED */
 int VID_FLAG = 0; /*flag if start of VID reconised*/
 int FPL_FLAG = 0; /*flag for if FPL*/
 int DIL_FLAG = 0; /*flag for if DIL is reconised*/
 int OIL_FLAG = 0; /*flag for if octal literal is reconised*/
 int ZERO_FLAG = 0; /*flag for if first digit is a 0*/
 int NUM_FLAG = 0; /*flag if number of unknown type is reconised*/
 int i; /*generic counter for a for loop*/
 
 lexstart = sc_buf->addc_offset;
 forward = lexstart;
				
 while (1)/*constant used for infinite loop*/
 { 
	 c = sc_buf->ca_head[forward++];  /*may need to be ++forward if getting wierd errors*/

	 if (isalnum(c)==0 || c=='"')
	 {
		 switch (c)
		 {
		 case '"':
			 {
				 ca_setmark(sc_buf,forward);
				 c = sc_buf->ca_head[forward++];
				 if (c != '"') /*checks to see if it is an empty string*/
				 {
					 while (c = sc_buf->ca_head[forward++])
					 {
						 if (c=='\n' || c=='\r') /*potential weird string error*/
						 {
							 t.code = ERR_T;
							 if ((forward - ca_getmark(sc_buf)) >= 20)
							 {
								 for (i=0;i<17;i++)
								 {
									 t.attribute.err_lex[i] = sc_buf->ca_head[ca_getmark(sc_buf)+1];
								 }
								 t.attribute.err_lex[17]='.';
								 t.attribute.err_lex[18]='.';
								 t.attribute.err_lex[19]='.';
								 t.attribute.err_lex[20]='\0';
							 }
							 else
							 {
								 for (i=0;i<20;i++)
								 {
									 t.attribute.err_lex[i]= sc_buf->ca_head[ca_getmark(sc_buf)+1];
								 }
								 t.attribute.err_lex[20]='\0';
							 }
						 }
						 if (c == '"') 
						 {
							 t.attribute.str_offset = str_LTBL->addc_offset;
							 for (i=(ca_getmark(sc_buf)+1);i<forward;i++) /*forward may point to 1 past the quotation mark*/
							 {
								 ca_addc(str_LTBL,sc_buf->ca_head[i]);
							 }
							 ca_addc(str_LTBL,'\0'); /*end of string marker*/
							 t.code = STR_T;
						 }
					 }
				 }
				 else
				 {
					 t.code = ERR_T;
					 t.attribute.err_lex[0]='R';
					 t.attribute.err_lex[1]='U';
					 t.attribute.err_lex[2]='N';
					 t.attribute.err_lex[3]=' ';
					 t.attribute.err_lex[4]='T';
					 t.attribute.err_lex[5]='I';
					 t.attribute.err_lex[6]='M';
					 t.attribute.err_lex[7]='E';
					 t.attribute.err_lex[8]=' ';
					 t.attribute.err_lex[9]='E';
					 t.attribute.err_lex[10]='R';
					 t.attribute.err_lex[11]='R';
					 t.attribute.err_lex[12]='O';
					 t.attribute.err_lex[13]='R';
					 t.attribute.err_lex[14]=':';
					 t.attribute.err_lex[15]='\0';
				 }
				 break;
			 }
		 case '+':
			 {
				 t.code = ART_OP_T;
				 t.attribute.arr_op = PLUS;
				 break;
			 }

		 case '-':
			 {
				 t.code = ART_OP_T;
				 t.attribute.arr_op = MINUS;
				 break;
			 }

		 case '*':
			 {
				 t.code = ART_OP_T;
				 t.attribute.arr_op = MULT;
				 break;
			 }

		 case '/':
			 {
				 t.code = ART_OP_T;
				 t.attribute.arr_op = DIV;
				 break;
			 }

		 case '{':
			 {
				 t.code = LPR_T;
				 break;
			 }

		 case '}':
			 {
				 t.code = RPR_T;
				 break;
			 }

		 case '>':
			 {
				 t.code = REL_OP_T;
				 t.attribute.rel_op = GT;
				 break;
			 }

		 case '<':
			 {
				 t.code = REL_OP_T;
				 t.attribute.rel_op = LT;
				 break;
			 }

		 case '=':
			 {
				 if (sc_buf->ca_head[forward++] == '=')
				 {
					 t.code = REL_OP_T;
					 t.attribute.rel_op = EQ;
				 }
				 else
				 {
					 forward--;
					t.code = ASS_OP_T;
				 }
				 break;
			 }

		 case ' ':
			 {
				 //c = sc_buf->ca_head[forward++];
				 break;
			 }
		 case '.':
			 {	
				 c= sc_buf->ca_head[forward++];
				 if (c == 'A')
				 {	
					 c= sc_buf->ca_head[forward++];
					 if (c == 'N')
					 {
						 c = sc_buf->ca_head[forward++];
						 if (c =='D')
						 {
							 t.code = LOG_OP_T;
							 t.attribute.log_op = AND;
						 }
						 else
						 {
							 t.code = ERR_T;
						 }
					 }
					 else
					 {
						 t.code = ERR_T;
					 }
				 }
				 if (c == 'O')
				 {
					 c = sc_buf->ca_head[forward++];
					 if (c == 'R')
					 {
						 t.code = LOG_OP_T;
						 t.attribute.log_op = OR;
					 }
					 else 
					 {
						 t.code = ERR_T;
					 }
				 }
				 else
				 {
					 t.code = ERR_T;
				 }
				 break;
			 }
		 case '!':
			 {	
				 c = sc_buf->ca_head[forward++];
				 if (c != '<')
				 {
					 t.code = ERR_T;
					 forward--;
				 }
				 if (c == '=')
				 {
					 t.code = REL_OP_T;
					 t.attribute.rel_op = NE;
				 }
				 else
				 {
					 while (sc_buf->ca_head[forward++] != '\n'){} //move through buffer untill comment is done
				 }
				 break;
			 }
		 case ';':
			 {
				 t.code = EOS_T;
				 break;
			 }
		 case '(':
			 {
				 t.code = LBR_T;
				 break;
			 }
		 case ')':
			 {
				 t.code = RBR_T;
				 break;
			 }
		 case EOF:
			 {
				 t.code=SEOF_T;
				 break;
			 }
		 default:/* may pick up others like string, so wierd errors could come from here*/
			 {
				 t.code = ERR_T;
				 t.attribute.err_lex[0] = c;
				 t.attribute.err_lex[1] = '/0'; /*store end of string inidicator to the string*/
				 break;
			 }
		 }
	 }
	 else /*character is a digit or letter*/
		 /*final state machine*/
	 {
		 ca_setmark(sc_buf,forward);
		 
		 state = 0;
		 lexstart = ca_getmark(sc_buf);
		 state = get_next_state (state,c,&accept);

		 c = sc_buf->ca_head[forward++];

		 while (accept == NOAS)
			 {
				 state = get_next_state(state,c,&accept);
				 if (accept == NOAS) /*if statemet to check if sate has changed*/
				 {
					 c = sc_buf->ca_head[forward++];
				 }
			 }

		 lex_buf = b_create(sc_buf->capacity,sc_buf->inc_factor,sc_buf->mode);

		 if (state == (2||7||8||11))
		 {
			 forward = lexstart;
		 }
		 
		 c = sc_buf->ca_head[lexstart];

		 while (1)
		 {
			 switch (c)/*character most recently added in*/
			 {
			 case 0: /*[a-zA-Z]*/
				 {
					 /*VID or SVID or Keyword may need to take this out check w/ leland*/
					 if (iskeyword(lex_buf->ca_head) != FALSE) /*keyword token found*/
					 {
						 if (lex_buf->addc_offset>0)
						 {
							 forward--; /*character not added to lex_buf move pointer back 1*/
						 }
						 t.code = KW_T;
						 t.attribute.kwt_idx = iskeyword(lex_buf->ca_head); /*set attribute*/
					 }
					 else
					 {
						 /*check to see if any of the identifier flags have been checked*/
						 if (FPL_FLAG!=0||DIL_FLAG!=0||OIL_FLAG!=0||NUM_FLAG!=0)
						 {
							 if (FPL_FLAG == 1) 
							 {
								 if (lex_buf->addc_offset>0)
								 {
									 forward--; /*character not added to lex_buf move pointer back 1*/
								 }
								 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
								 t=aa_table[8](lex_buf->ca_head);
							 }
							 if (DIL_FLAG == 1) 
							 {
								 if (lex_buf->addc_offset>0)
								 {
									 forward--; /*character not added to lex_buf move pointer back 1*/
								 }
								 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
								 t=aa_table[7](lex_buf->ca_head);

							 }
							 if (OIL_FLAG == 1) 
							 {
								 if (lex_buf->addc_offset>0)
								 {
									 forward--; /*character not added to lex_buf move pointer back 1*/
								 }
								 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
								 t=aa_table[12](lex_buf->ca_head);
							 }
							 if (ZERO_FLAG == 1) 
							 {
								 if (lex_buf->addc_offset>0)
								 {
									 forward--; /*character not added to lex_buf move pointer back 1*/
								 }
								 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
								 t=aa_table[7](lex_buf->ca_head);
							 }
							 if (NUM_FLAG==1&&ZERO_FLAG==0) 
							 {
								 if (lex_buf->addc_offset>0)
								 {
									 forward--; /*character not added to lex_buf move pointer back 1*/
								 }
								 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
								 t=aa_table[7](lex_buf->ca_head);
							 }

						 }
						 VID_FLAG = 1; /*set variable identifier flag*/
					 }
					 ca_addc(lex_buf,c);
					 break;
				 }
			 case 1: /*0*/
				 {
					 /*octal or DIL 0 or FPL 0*/
					 if (ZERO_FLAG==1)/*leading 0 and another digit*/
					 {
						 OIL_FLAG=1;
					 }
					 if (FPL_FLAG==0&&NUM_FLAG==0&&DIL_FLAG==0&&ZERO_FLAG==0)
					 {
						 ZERO_FLAG=1; /*identify as a numeric token starting with 0*/
					 }
					 if (NUM_FLAG==1&&ZERO_FLAG==0) /*number with no leading 0*/
					 {
						 /*could be FPL or DIL*/
					 }
					 if (VID_FLAG==1)
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 VID_FLAG=1;
					 }
					 /*if FPL_FLAG is set it is known to be an FPL*/
					 ca_addc(lex_buf,c);
					 break;
				 }
			 case 2: /*[8-9]*/ 
				 {
					 if (ZERO_FLAG==1&&FPL_FLAG==0&&OIL_FLAG==0&&DIL_FLAG==0)/*leading 0 and no decimal place*/
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 /*number is single 0*/
						 if (lex_buf->addc_offset > 0)
						 {
							 forward--;
						 }
						 t=aa_table[7](lex_buf->ca_head);
					 }
					 if (OIL_FLAG==1)
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG); /*reset the flags*/
						 if (lex_buf->addc_offset > 0)
						 {
							 forward--; 
						 }
						 t=aa_table[12](lex_buf->ca_head);

					 }
					 if (NUM_FLAG==0&&DIL_FLAG==0&&FPL_FLAG==0) /*no preceeding digits*/
					 {
						 /*could be a DIL or FPL*/
						 NUM_FLAG=1;
					 }
					 if (VID_FLAG==1)/*is already known VID*/
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 VID_FLAG=1;
					 }
					 ca_addc(lex_buf,c);
					 break;
				 }
			 case 3: /*[1-7]*/
				 {
					 if (ZERO_FLAG==1&&OIL_FLAG==1) /*already known oil*/
					 {
						 /*still oil*/
					 }
					 if (ZERO_FLAG==1&&OIL_FLAG==0)/*leading 0 with no other digits*/
					 {
						 OIL_FLAG=1;
					 }
					 if (NUM_FLAG==0&&FPL_FLAG==0&&DIL_FLAG==0)/*no numeric flags set*/
					 {
						 NUM_FLAG=1;
					 }
					 if (VID_FLAG==1)
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 VID_FLAG=1;
					 }
					 ca_addc(lex_buf,c);
					 break;
				 }
			 case 4: /*.*/
				 {
					 if (NUM_FLAG==0&&ZERO_FLAG==0&&DIL_FLAG==0&&FPL_FLAG==0)/*if no numeric flags are set*/
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 ca_addc(lex_buf,c);
						 t=aa_table[9](lex_buf->ca_head);
					 }
					 if (OIL_FLAG==1) /*if known OIL*/
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 ca_addc(lex_buf,c);
						 t=aa_table[9](lex_buf->ca_head);
					 }
					  if (FPL_FLAG==1) /*if known FPL*/
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 ca_addc(lex_buf,c);
						 t=aa_table[9](lex_buf->ca_head);
					 }
					 if ((DIL_FLAG==1||NUM_FLAG==1)&&FPL_FLAG==0)/*if identified as a DIL or NUM already*/
					 {
						 FPL_FLAG=1;
					 }
					 if (VID_FLAG==1) /*if VID*/
					 {
						 if (lex_buf->addc_offset>0)
						 {
							 forward--; /*character not added to lex_buf move pointer back 1*/
						 }
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 t=aa_table[3](lex_buf->ca_head);
					 }
					 ca_addc(lex_buf,c);
					 break;
				 }
			 case 5: /*#*/
				 {
					 if (VID_FLAG==0&&FPL_FLAG==0&&DIL_FLAG==0&&OIL_FLAG==0&&ZERO_FLAG==0)
					 {
						 ca_addc(lex_buf,c);
						 t=aa_table[9](lex_buf->ca_head);
					 }
					 if (FPL_FLAG==1)
					 {
						 if(lex_buf->addc_offset>0)
						 {
							 forward--;
						 }
						 t=aa_table[8](lex_buf->ca_head);
					 }
					 if (VID_FLAG==1)
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 ca_addc(lex_buf,c);
						 t=aa_table[2](lex_buf->ca_head);
					 }
					 break;
				 }
			 case 6: /*other*/
				 {
					 if (lex_buf->addc_offset!=0)
					 {
						 sc_buf->addc_offset--; /*character never written to lex_buf set pointer back 1*/
					 }
					 if ((c==';'||c ==' ')&&VID_FLAG==1)
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 t = aa_table[2](lex_buf->ca_head);
					 }
					 if ((c==';'||c ==' ')&&FPL_FLAG==1)
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 t=aa_table[8](lex_buf->ca_head);
					 }
					 if ((c==';'||c ==' ')&&DIL_FLAG==1)
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 t=aa_table[7](lex_buf->ca_head);
					 }
					 if ((c==';'||c ==' ')&&OIL_FLAG==1)
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 t=aa_table[11](lex_buf->ca_head);
					 }
					 if ((c==';'||c ==' ')&&NUM_FLAG==1)
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 t=aa_table[11](lex_buf->ca_head);
					 }
					 if ((c==';'||c ==' ')&&ZERO_FLAG==1)
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 t=aa_table[7](lex_buf->ca_head);
					 }
					 else
					 {
						 reset_flags(&FPL_FLAG,&DIL_FLAG,&OIL_FLAG,&ZERO_FLAG,&VID_FLAG,&NUM_FLAG);
						 ca_addc(lex_buf,c);
						 t=aa_table[9](lex_buf->ca_head);
					 }
					 break;
				 }
			 }
			 c=(lex_buf,sc_buf->ca_head[forward++]);/*add next character to the buffer*/
		 }
	 }
	 b_destroy(lex_buf);
	 return t;               
   }//end while(1)
}