#include #include #include #include #include "colorer.h" keyedValueArray instLinks = {0, 0}; keyedValueArray dirLinks = {0, 0}; char* buffer = NULL; int bufferSize = 0; char* csspath = NULL; char* linkspath = NULL; char* name = NULL; int fillTabs = 0; int keywordsDetected = 0; char sxInstBuf[32]; //buffer for storing a detected sx mnemonic char sxTemplateBuf[32]; /*buffer for storing a detected sx mnemonic and operands template (see pic.l for more info) */ char sxOperandsString[256]; /* buffer for temporary storage of original operands string */ void stylePrint(char* style, char* text) { if(csspath != NULL) { fprintf(yyout, "%s", style, text); } else { fprintf(yyout, "%s", text); } } void stylePrintSkipLast(char* style, char* text) { char* x; x = _strdup(text); x[strlen(text) - 1] = 0; //remove look ahead character stylePrint(style, x); unput(text[strlen(text) - 1]); //put look ahead character back on stream free(x); } void stylePrintSkipLastAndLink(char* style, char* text, keyedValueArray* arr) { char* x; char* url; x = _strdup(text); x[strlen(text) - 1] = 0; //remove look ahead character if(linkspath == NULL) { stylePrint(style, x); } else { url = getValue(arr, x); //find if it has a link if(url == NULL) { stylePrint(style, x); } else { fprintf(yyout, "%s", url, style, x); } } unput(text[strlen(text) - 1]); //put look ahead character back on stream free(x); return; } void stylePrintAndLinkToOr(char* style, char* text, keyedValueArray* arr, char* key) { /* Style print text and link it to or if not found try to link it to */ char* url; if(linkspath == NULL) { stylePrint(style, text); return; } url = getValue(arr, key); //find if it has a link if(url == NULL) { //try another variant url = getValue(arr, text); if(url == NULL) { stylePrint(style, text); return; } } //link found fprintf(yyout, "%s", url, style, text); return; } int mainConsole(int argc, char *argv[ ], char *envp[ ]) { char isHTML = 0; int result; yyin = NULL; yyout = stdout; //check command line argv = checkCommandLine(argc, argv, envp); if(argv == 0) { return(1); } //open input file yyin = fopen(name, "r"); if(yyin == NULL) { error("Couldn't open the file"); return(1); } //read links result = readLinksFrom(linkspath); if(result != 0) { return(result); } //check if file is HTML name = strrchr(name, '.'); //find last dot in name if(name != NULL && _strnicmp(name, ".htm", 4) == 0) { isHTML = 1; } //convert non HTML file to HTML if(!isHTML) { //substitute input file with a temporary //one, converted to HTML yyin = convertFileToHTML(yyin); if(yyin == NULL) { return(1); } } yylex(); freeKeyedValueArray(&instLinks); freeKeyedValueArray(&dirLinks); fclose(yyin); return(0); } void putInBuffer(char* text) { if(buffer == NULL) { //create buffer buffer = _strdup(text); bufferSize = strlen(buffer); } else { //append to buffer bufferSize += strlen(text); //length of added text buffer = (char*)realloc(buffer, (bufferSize + 1) * sizeof(char)); strcat(buffer, text); //copy text to end of buffer } } void printBuffer() { if(buffer != NULL) { fprintf(yyout, "%s", buffer); freeBuffer(); } } void unputBuffer() { int y; if(buffer != NULL) { y = bufferSize; while(y-- != 0) { unput(buffer[y]); } freeBuffer(); } } void freeBuffer() { free(buffer); buffer = NULL; bufferSize = 0; } char** checkCommandLine(int argc, char *argv[ ], char *envp[ ]) { if(*(argv + 1) == NULL) { helpScreen(); return(0); } while(*++argv) { if(argv[0][0] == '-') { switch(argv[0][1]) { case 'h': helpScreen(); break; case 'l': //links file path linkspath = argv[1]; if(linkspath == NULL) { error("Enter links mapping file path after -l option"); return(0); } argv++; break; case 's': //style sheet file path csspath = argv[1]; if(csspath == NULL) { error("Enter style sheet URL after -s option"); return(0); } argv++; break; case 't': if(argv[1] != NULL) { fillTabs = atoi(argv[1]); } if(fillTabs <= 0 || fillTabs > 10) { error("Tabs can only have size in the range 1..10"); return(0); } argv++; break; default: error("Unknown option"); return(0); break; } } else { //input file path name = argv[0]; break; } } if(name == NULL) { error("Specify file name"); return(0); } return(argv); } void error(char* message) { fprintf(yyout, "ERROR> %s\n", message); } void helpScreen() { static char printed = 0; if(!printed) { printed = 1; fprintf(yyout, "--------------------------------------------------------------------\n"); fprintf(yyout, "ASSEMBLER COLORER/CODE TO HTML CONVERTER\n"); fprintf(yyout, "for MPASM, SASM, and SX-Key syntax\n"); fprintf(yyout, "(c) 2000 by Nikolai Golovchenko\n"); fprintf(yyout, "--------------------------------------------------------------------\n"); fprintf(yyout, "Command line:\n\tcolorer.exe {options} source_file {> destination_file}\n"); fprintf(yyout, "Options:\n\t-s \"css_url\"\tStyle sheet URL\n"); fprintf(yyout, "\t-t tab_size\tReplace tabs with spaces when converting code to HTML\n"); fprintf(yyout, "\t-l \"links_file\"\tMap keywords to links\n"); fprintf(yyout, "\t-h\t\tHelp (this screen)\n"); fprintf(yyout, "Note:\n\t1) source_file - plain text or HTML file\n"); fprintf(yyout, "\t2) If -s option is absent, just conversion to HTML is performed\n"); fprintf(yyout, "\t3) Used style sheet classes:\n"); fprintf(yyout, "\t\tInst\tInstructions"); fprintf(yyout, "\t\tNum\tNumbers\n"); fprintf(yyout, "\t\tDir\tDirectives"); fprintf(yyout, "\t\tStr\tStrings\n"); fprintf(yyout, "\t\tSym\tSymbols, operators"); fprintf(yyout, "\tComm\tComments\n"); fprintf(yyout, "Example:\n\tcolorer.exe -s \"/styles/asm.css\" -t 8 in.asm > out.htm\n"); fprintf(yyout, "\tcolorer.exe -t 3 main.cpp > out.htm\n"); fprintf(yyout, "--------------------------------------------------------------------\n"); } } void addKeyAndValue(keyedValueArray* arr, char* key, char* value) { arr->head = (struct KEYEDVALUE*)realloc(arr->head, (arr->size + 1) * sizeof(keyedValue)); strcpy((arr->head + arr->size)->key, key); strcpy((arr->head + arr->size)->value, value); arr->size++; } void freeKeyedValueArray(keyedValueArray* arr) { if(arr->size != 0) { free(arr->head); arr->size = 0; arr->head = 0; } } char* getValue(keyedValueArray* arr, char* key) { int i; for(i = 0; i < arr->size; i++) { if(_stricmp(key, (arr->head + i)->key) == 0) { return((arr->head + i)->value); } } return(NULL); } char readLinksFile(FILE* links) { int state = 0; int i = 0; keyedValueArray* arr; char key[256]; char value[256]; char cssclass[256]; char result = 0; char ch; while(fread(&ch, 1, 1, links) == 1 && result == 0) { // states: // 0 - looking for ->Class // 1 - reading Class // 2 - looking for key // 3 - reading key // 4 - looking for value // 5 - reading value // switch(state) { case 0: //looking for .class if(ch == '.') { state = 1; i = 0; } else if(!isspace(ch)) { error("Links file> Class name should start from dot '.'"); return(1); } break; case 1: //reading class name if(isalpha(ch)) { cssclass[i++] = ch; } else if(isspace(ch)) { cssclass[i] = '\0'; i = 0; if(_stricmp(cssclass, "Inst") == 0) { arr = &instLinks; } else if(_stricmp(cssclass, "Dir") == 0) { arr = &dirLinks; } else { error("Links file> Can't recognize .class name"); return(1); } state = 2; } else { error("Links file> Class name should be separated by a whitespace"); return(1); } break; case 2: //looking for key if(isalpha(ch) || ch == '$' || ch == '#') { key[i++] = ch; state = 3; } else if(i == 0 && ch == '.') { state = 1; } else if(!isspace(ch)) { error("Links file> A keyword should start from a letter, $, or #"); return(1); } break; case 3: //reading key if(isalpha(ch) || ch == ',' || ch == '-' || ch == '+' || ch == '/' || ch == '>' || ch == '<' || ch == '!' || ch == '#' || ch == '_' /*|| ch == ';' //> < || ch == '&'*/) { if(i <= 250 && ch == '>') { key[i++] = '&'; key[i++] = 'g'; key[i++] = 't'; key[i++] = ';'; } else if(i <= 250 && ch == '<') { key[i++] = '&'; key[i++] = 'l'; key[i++] = 't'; key[i++] = ';'; } else { key[i++] = ch; } } else if(ch == ':') { key[i] = '\0'; i = 0; state = 4; } else if(!isspace(ch)) { error("Links file> A keyword should be separated by a colon"); return(1); } break; case 4: //looking for a value if(!isspace(ch)) { value[i++] = ch; state = 5; } break; case 5: //reading a value if(!isspace(ch)) { value[i++] = ch; } else { value[i] = '\0'; i = 0; state = 2; //add key-value addKeyAndValue(arr, key, value); } break; default: break; } if(i >= 255) { error("Links file> String can be maximum 255 characters long"); return(1); } } return(0); } int readLinksFrom(char* linkspath) { FILE* links; if(linkspath != NULL) { links = fopen(linkspath, "r"); if(links == NULL) { error("Couldn't open the links file"); return(1); } if(readLinksFile(links) != 0) { freeKeyedValueArray(&instLinks); freeKeyedValueArray(&dirLinks); fclose(links); return(1); } fclose(links); } return(0); } FILE* convertFileToHTML(FILE* fin) { char ch; FILE* fout; fpos_t filestart=0; int pos; int spaces; //create temporary file fout = tmpfile(); if(fout != NULL) { pos = 0; //initialize line position fprintf(fout, "\n\n\n\n\n"); fprintf(fout, "
\n");
		while(fread(&ch, 1, 1, fin) == 1)
		{
			pos++; //advance one position
			switch(ch)
			{
			case '\t':
				if(fillTabs != 0)
				{
					spaces = pos - 1; //old position
					pos = spaces - spaces % fillTabs + fillTabs; //new position
					spaces = pos - spaces; //difference
					while(spaces != 0)
					{
						fprintf(fout, " ");
						spaces--;
					}
				}
				else
				{
					fprintf(fout, "\t");
				}
				break;
			case '\n':
				pos = 0; //reset position
				fprintf(fout, "\n");
				break;
			case '<':
				fprintf(fout, "<");
				break;
			case '>':
				fprintf(fout, ">");
				break;
			case '&':
				fprintf(fout, "&");
				break;
			case '\"':
				fprintf(fout, """);
				break;
			default:
				fprintf(fout, "%.1s", &ch);
				break;
			}

		}
		fprintf(fout, "\n
\n"); fprintf(fout, "\n\n"); fclose(fin); fsetpos(fout, &filestart); } return(fout); }