Jump to content

This Has To Be The Most C Code I Have Typed Ever


markiemrboo

Recommended Posts

Hooray :) I tested it on Windows and FreeBSD, although on Windows I had to #ifdef out the whole command line getopt() bit, but my menu still works on it! I should probably seperate things out into another file or two. Still gotta do the whole interpret instruction thing too :)

 

main.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>

#ifdef _WIN32
 #include <error.h>
 #define err(s, n) exit(s)
 #define strcasestr strstr
 #define bzero(s, n) memset((s), 0, (n))
#else
 #include <err.h>
 #include <unistd.h>
#endif

#include <stdlib.h>

#define PROGLOAD_OK 0
#define PROGLOAD_NOMEM -1
#define PROGLOAD_BADMEM -2
#define PROGLOAD_NOFILE -3

#define MENU_LOAD 1
#define MENU_EXIT 0
#define MENU_DEBUG 3
#define MENU_RESET 2
#define MENU_RUN 4
#define MENU_INVALID -1

#define MENU_MAX 4
#define MENU_MIN 0

/* STRUCTURES */
typedef struct {
char **RAM;
char *Reg;
int szReg;
int szRAM;
} systemMem;

typedef struct {
int instructions;
int comments;
int programLoaded;
} systemStats;

/* FUNCTION PROTOTYPES */
void PrintUsage(void); 
int LoadProgram(char *, systemMem *, systemStats *);
int InitSystem(systemMem *, systemStats *);
FILE *OpenFile(char *, char *);
void CloseFile(FILE *);
void ShowMenu(void);
int GetChoice(char *, char *);
void ProcessChoice(int *, char *);

/* VARIABLES */
int loadCmdLine = 0;
int dflag = 0;
struct stat sb;
systemMem sm;
systemStats ss;

/* FUNCTIONS */
int main(int argc, char **argv) {
int option = 0, optionChosen = MENU_INVALID;
char *pFilename = NULL, *pOptionStr = NULL, optionInput[512];

bzero(&ss, sizeof(systemStats));
bzero(&sm, sizeof(systemMem));

#ifndef _WIN32
while ( (option = getopt(argc, argv, "d")) != -1 ) {
 switch(option) {
	 case 'd': {
   dflag = 1;
   break;
	 }

	 case '?':
	 default: {
   PrintUsage();
   return -1;
	 }
 }	
}

while (optind < argc) {
 if (stat(argv[optind], &sb) == 0) {
	 pFilename = argv[optind];
 } else {
	 err(1, NULL);
 }

 optind++;
}
#endif

InitSystem(&sm, &ss);

while (optionChosen != MENU_EXIT) {
 if (pFilename == NULL) {
	 optionChosen = MENU_INVALID;
	 ShowMenu();

	 do {
   printf("> ");
   pOptionStr = fgets(optionInput, 512, stdin);
   optionChosen = GetChoice(pOptionStr, optionInput);
	 } while (optionChosen < MENU_MIN || optionChosen > MENU_MAX);
 } else {
	 pOptionStr = pFilename;

	 if (optionChosen == MENU_RUN && loadCmdLine == 1) {
   pFilename = NULL;
	 } else {
   optionChosen = MENU_LOAD;
   loadCmdLine = 1;
	 }
 }

 ProcessChoice(&optionChosen, pOptionStr);
}

printf("Goodbye!\n");

return 0;
}

int InitSystem(systemMem *sm, systemStats *ss) {
if (sm->szReg < 1)
 sm->szReg= 16;

if (sm->szRAM < 1)
 sm->szRAM = 1024;

/* Init memory stuffs */
sm->RAM = (char **)malloc(sizeof(char *) * sm->szRAM);
assert(sm->RAM != NULL);
sm->Reg = (char *)malloc(sizeof(char) * sm->szReg); 
assert(sm->Reg != NULL);

return 0;
}

/* 
* Reads program from file and loads into RAM 
*/
int LoadProgram(char *filename, systemMem *sm, systemStats *ss) {
int i = 0, matches = 0, currentLine = 0, ramIndex = 0, comments = 0;
char *pStr = NULL, *line = NULL;
FILE *fd = NULL;

/* check errors */
if (stat(filename, &sb) != 0)
 return PROGLOAD_NOFILE;

if (sm->RAM == NULL || sm->szRAM < 1 || sm->Reg == NULL || sm->szReg < 1)
 return PROGLOAD_BADMEM;

line = (char *)malloc(sizeof(char) * 100);
assert(line != NULL);

/* open file */
fd = OpenFile(filename, "r");

if (dflag == 1)
 printf("RAM Dump:\n");

ss->comments = 0;

/* read from file */
while (!feof(fd) && ramIndex < sm->szRAM) {
 pStr = fgets(line, 100, fd);
 if (pStr == NULL) {
	 if (!feof(fd))
   err(1, NULL);
	 break;
 }

 currentLine++;
 if (strchr(pStr, ';') != NULL)
	 ss->comments++;

 matches = 0;
 for (i = 0; i < 8; i++) {
	 pStr[i] = toupper(pStr[i]);
	 if (isdigit(pStr[i]) || (pStr[i] >= 'A' && pStr[i] <= 'F')) {
   matches++;
	 }
 }

 if (matches == 8) {
	 sm->RAM[ramIndex] = (char *)malloc(sizeof(char) * 9);
	 assert(sm->RAM[ramIndex] != NULL);
	 strncpy(sm->RAM[ramIndex], pStr, 8); 

	 if (dflag == 1)
   printf("%s\n", sm->RAM[ramIndex]);

	 ramIndex++;
 } else {
	 if (strchr(line, ';') == NULL) {
   printf("Bad Line (%d): %s\n", currentLine, line);
   exit(2);
	 }
 }
}

CloseFile(fd);

free(line);
line = NULL;

if (dflag == 1)
 printf("\nRegister Dump:\n");

for (i = 0; i < sm->szReg; i++) {
 sm->Reg[i] = 0;
 if (dflag == 1) {
	 printf("R%d = %d\n", i, sm->Reg[i]);
 }
}
if (dflag == 1)
 printf("\n");

ss->instructions = ramIndex;
ss->comments = 0;
ss->programLoaded = 1;

/* out of memory */
if (sm->szRAM == ramIndex)
 return PROGLOAD_NOMEM;

/* all good? */
return PROGLOAD_OK;
}

/*
* Try to open file and return descriptor
*/
FILE *OpenFile(char *filename, char *mode) {
FILE *fd;

fd = fopen(filename, mode);
if (fd == NULL) {
 err(1, NULL);
}

return fd;
}

/*
* Try to close file
*/
void CloseFile(FILE *fd) {
if (fclose(fd) != 0) {
 err(1, NULL);
}
}

/*
* Might print usage one day!
*/
void PrintUsage(void) {
return;
}

/*
* Display interactive menu
*/
void ShowMenu(void) {
printf("==============\nMIPS Simulator\n==============\n");
printf(" o load filename\tLoad file, filename, into RAM\n");
printf(" o reset\t\tReset simulator\n");
printf(" o debug [on|off]\tTurn debugging on/off. Currently %s\n", (dflag ? "on" : "off"));
printf(" o run\t\t\tRun program\n");
printf(" o exit\t\t\tExit!!\n");
}

/* 
* Get choice number from string 
*/
int GetChoice(char *pOptionStr, char *optionInput) {
int optionChosen = MENU_INVALID;

/* XXX: ^D triggers this for some reason, FIX */
assert(pOptionStr != NULL);

if (strcasestr(pOptionStr, "lo") == optionInput) {
 optionChosen = MENU_LOAD;
} else if (strcasestr(pOptionStr, "re") == optionInput) {
 optionChosen = MENU_RESET;
} else if (strcasestr(pOptionStr, "de") == optionInput) {
 optionChosen = MENU_DEBUG;
} else if (strcasestr(pOptionStr, "ex") == optionInput) {
 optionChosen = MENU_EXIT;
} else if (strcasestr(pOptionStr, "ru") == optionInput) {
 optionChosen = MENU_RUN;
} else {
 printf("Invalid option\n");
 optionChosen = MENU_INVALID;
}

return optionChosen;
}

void ProcessChoice(int *optionChosen, char *pOptionStr) {
int loadRet = 0, cI = 0;

switch(*optionChosen) {
 case MENU_EXIT: {
	 break;
 }

 /* load */
 case MENU_LOAD: {
	 if (loadCmdLine != 1)
   pOptionStr = strchr(pOptionStr, ' ');

	 if (pOptionStr != NULL) {
   if (loadCmdLine == 1) {
  	 *optionChosen = MENU_RUN;
   } else {
  	 pOptionStr++;
  	 *strchr(pOptionStr, '\n') = '\0';
   }

   loadRet = LoadProgram(pOptionStr, &sm, &ss);
   switch(loadRet) {
  	 /* stat file failed */
  	 case PROGLOAD_NOFILE: {
     printf("File doesn't exist\n");
     break;
  	 }

  	 case PROGLOAD_BADMEM: {
     printf("Setup system memory please?\n");
     *optionChosen = MENU_EXIT;
     break;
  	 }

  	 case PROGLOAD_NOMEM: {
     printf("Out of memory, increase simulator RAM size?\n");
     *optionChosen = MENU_EXIT;
     break;
  	 }

  	 default: {
     printf("Program loaded\n");
  	 }
   }
	 } else {
   printf("Must specify filename\n");
	 }

	 break;
 }

 /* reset */
 case MENU_RESET: {
	 printf("Resetting..\n");
	 
	 break;
 }

 /* debug */
 case MENU_DEBUG: {
	 pOptionStr = strchr(pOptionStr, ' ');
	 dflag = !dflag;

	 if (pOptionStr != NULL) {
   pOptionStr++;
   if (strcasestr(pOptionStr, "on"))
  	 dflag = 1;
   else if (strcasestr(pOptionStr, "off"))
  	 dflag = 0;
	 }

	 break;
 }

 case MENU_RUN: {
	 if (ss.programLoaded == 1) {
   for (cI = 0; cI < ss.instructions; cI++) {
  	 printf("<Executing: %s>\n", sm.RAM[cI]);
   }
	 } else {
   printf("No program loaded\n");
	 }

	 if (loadCmdLine == 1) {
   loadCmdLine = 0;
	 }

	 break;
 }

 case MENU_INVALID: {
	 break;
 }

 default: {
	 printf("Shouldn't be here?\n");	
 }
}
}

 

and here's a file you can load into the program.

 

helloworld.mips

24050002
00a51020
3c010000
3424001c
0000000c
2402000a
0000000c
48656c6c; 'Hell'
6f20576f; 'o Wo'
726c6421; 'rld!'
0a000000; '\n  '

 

Impressive huh? :lol: I feel like I am getting better, atleast knowing the ins and outs of the language and how to use it... the actual implementation so far is probably a giant steaming piece of .... mess :) Still... it's progress!

Share this post


Link to post
Share on other sites

About a year ago I wrote a pretty cool c++ game I dubbed space invaders (how original). It had a completely external level editor, random paralax graphics (the stars are produced randomly and move at different speeds), and full functionality.

 

Unfortunately, I accidentally deleted it at school, and my backup floppy fubared in the same day. Too bad, it was my baby. :(

 

Here is one of the only screenshots I still have of it. Keep in mind, I like to program, not design spaceships. :P

Share this post


Link to post
Share on other sites

That is pretty impressive markie! Well, it is to me! :P

 

Im only starting to get the hang of Java, it's not too bad. We don't even need to learn C++ yet. Probbaly in a year or two, thank god! :)

:lol: You shouldn't have a lot of difficulty going from Java->C/++ if you really get the hang of Java, the language looks very much the same! I found pointers to be the most confusing thing, but I think I have the hang of those now too :D

 

Just got this massive impossible looking Java assignment today so I gotta try and get motivated to look at doing that now :)

 

Considering I am 19 and the dude who did the game is like... well, would have been like 14 when he started writing it. He is obviously very talented :) I'd have gone mental if I lost all that work too!

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...