Department of Electrical and Computer Engineering

The University of Texas at Austin


The following functions are provided for your benefit. Feel free to use them if you want. You are not required to use any of this code. It is provided to help you brush up on your C skills and to prevent you from spending a lot of effort writing a parser for your assembler.


To use the code provided below you need to include the following files in your code:

#include <stdio.h> /* standard input/output library */
#include <stdlib.h> /* Standard C Library */
#include <string.h> /* String operations library */
#include <ctype.h> /* Library for useful character operations */

Convert a string into a number
Hex numbers must be in the form "x3000", and decimal numbers must be in the form "#30"

int
toNum( char * pStr )
{
   char lBuf[10];
   int lNum, lNeg = 0;
   if( *pStr == '#' )				/* decimal */
	return atoi( pStr + 1 );
   else if( *pStr++ == 'x' || *pStr++ == 'X' )	/* hex     */
   {
      if( *pStr == '-' )				/* hex is negative */
      {
       lNeg = 1;
	pStr++;
      }
      sprintf( lBuf, "0x%s", pStr );		/* convert hex into decimal */
      sscanf( lBuf, "%i", &lNum );
      if( lNeg ) lNum = -lNum;
	return lNum;
   }
   else
   {
	printf( "Error: unknown constant, %s\n", pStr);
	exit( 3 );
   }
}

Another function to convert a string into a number

int
toNum(char * pStr) {
    
    if (*pStr == '#')
        
        return strtol(pStr + 1, NULL, 10);
    
    else if (*pStr == 'x' || *pStr == 'X') {
        
        if (*pStr + 1 == '-')
            return -strtol(pStr + 2, NULL, 16);
        else
            return strtol(pStr + 1, NULL, 16);
    
    } else {
        
        printf("Error: unknown constant, %s\n", pStr);
        exit(3);

    }
}


Take a line of the input file and parse it into corresponding fields. Note that you need to write the isOpcode(char*) function which determines whether a string of characters is a valid opcode.


	#define MAX_LINE_LENGTH 255
	enum
	{
	   DONE, OK, EMPTY_LINE
	};

	int
	readAndParse( FILE * pInfile, char * pLine, char ** pLabel, char
	** pOpcode, char ** pArg1, char ** pArg2, char ** pArg3, char ** pArg4
	)
	{
	   char * lRet, * lPtr;
	   int i;
	   if( !fgets( pLine, MAX_LINE_LENGTH, pInfile ) )
		return( DONE );
	   for( i = 0; i < strlen( pLine ); i++ )
		pLine[i] = tolower( pLine[i] );
	   
           /* convert entire line to lowercase */
	   *pLabel = *pOpcode = *pArg1 = *pArg2 = *pArg3 = *pArg4 = pLine + strlen(pLine);

	   /* ignore the comments */
	   lPtr = pLine;

	   while( *lPtr != ';' && *lPtr != '\0' &&
	   *lPtr != '\n' ) 
		lPtr++;

	   *lPtr = '\0';
	   if( !(lPtr = strtok( pLine, "\t\n ," ) ) ) 
		return( EMPTY_LINE );

	   if( isOpcode( lPtr ) == -1 && lPtr[0] != '.' ) /* found a label */
	   {
		*pLabel = lPtr;
		if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK );
	   }
	   
           *pOpcode = lPtr;

	   if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK );
	   
           *pArg1 = lPtr;
	   
           if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK );

	   *pArg2 = lPtr;
	   if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK );

	   *pArg3 = lPtr;

	   if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK );

	   *pArg4 = lPtr;

	   return( OK );
	}

	/* Note: MAX_LINE_LENGTH, OK, EMPTY_LINE, and DONE are defined values */

To call readAndParse, you would use the following: 
	func() 
	{
	   char lLine[MAX_LINE_LENGTH + 1], *lLabel, *lOpcode, *lArg1,
	        *lArg2, *lArg3, *lArg4;

	   int lRet;

	   FILE * lInfile;

	   lInfile = fopen( "data.in", "r" );	/* open the input file */

	   do
	   {
		lRet = readAndParse( lInfile, lLine, &lLabel,
			&lOpcode, &lArg1, &lArg2, &lArg3, &lArg4 );
		if( lRet != DONE && lRet != EMPTY_LINE )
		{
			...
		}
	   } while( lRet != DONE );
	}


To write to your output file, you can use the following:

	FILE * pOutfile;
	pOutfile = fopen( "data.out", "w" );
		
		...

	fprintf( pOutfile, "0x%0.4X\n", lInstr );	/* where lInstr is declared as an int */