Esempio n. 1
0
int main (int argc, char **argv)
{
	int curr_arg = 1;
	bool case_sensitive = false;
	bool is_storage_initialized = false;

	use_colors = true;
	extern WORD user_attributes;
	user_attributes = save_console_attributes ();
	atexit (restore_console_attributes_at_exit);

	//if there aren't enough args, show info
	if (argc < 2) {
		puts ("SPASM-ng Z80 Assembler by Spencer Putt and Don Straney");
		printf ("Version %s (built on %s @ %s)\n", SPASM_NG_VERSION, __DATE__, __TIME__);
#ifdef SPASM_NG_GITREV
		printf ("Git revision %s\n", SPASM_NG_GITREV);
#endif
#ifdef _M_X64
		puts ("64-bit Version");
#endif
#ifdef NO_APPSIGN
		printf ("\nApp signing is NOT available in this build of SPASM.\n");
#endif
		puts ("\nspasm [options] <input file> <output file>\n");
		puts ("Options:\n-E = Assemble eZ80 code\n-T = Generate code listing\n-C = Code counter mode\n-L = Symbol table mode\n-S = Stats mode\n-O = Don't write to output file");
		puts ("-I [directory] = Add include directory\n-A = Labels are cAse-sensitive\n-D<name>[=value] = Create a define 'name' [with 'value']");
		puts ("-N = Don't use colors for messages");
		puts ("-V <Expression> = Pipe expression directly into assembly");

#if defined(_DEBUG) && defined(WIN32)
		if (IsDebuggerPresent())
		{
			system("PAUSE");
		}
#endif
		return EXIT_NORMAL;
	}

	//init stuff
	mode = MODE_NORMAL;
	in_macro = 0;
	
	//otherwise, get any options
	curr_input_file = strdup("Commandline");
	char *starting_input_file = curr_input_file;

	while (curr_arg < argc) {
		if (argv[curr_arg][0] == '-'
#ifdef _WINDOWS
			|| argv[curr_arg][0] == '/'
#endif
			)
		{
			switch (argv[curr_arg][1])
			{
			//args for different modes
			case 'O':
				mode = mode & (~MODE_NORMAL);
				break;
			case 'T':
				mode |= MODE_LIST;
				break;
			case 'C':
				mode |= MODE_CODE_COUNTER;
				break;
			case 'L':
				mode |= MODE_SYMTABLE;
				break;
			case 'S':
				mode |= MODE_STATS;
				break;
			case 'E':
				mode |= MODE_EZ80;
				all_opcodes = opcode_list_ez80;
				break;
			//handle no-colors flag
			case 'N':
				use_colors = false;
				break;
			//handle include files too
			case 'I':
			{
				char *dir, *p;
				//make sure there's another argument after it for the include path
				if (strlen(argv[curr_arg]) > 2) {
					dir = strdup (&argv[curr_arg][2]);
				} else {
					if (curr_arg >= argc - 1) {
						printf ("%s used without include path\n", argv[curr_arg]);
						break;
					}
					
					dir = strdup (argv[++curr_arg]);
				}
				
				for (p = strtok (dir, ";,"); p; p = strtok (NULL, ";,")) {
					include_dirs = list_append (include_dirs, strdup(p));
				}
				free(dir);
				break;
			}
			//and the case-sensitive flag
			case 'A':
				case_sensitive = true;
				break;
			//handle adding defines
			case 'D':
			{
				char name[256];
				char *ptr;
				define_t *define;

				if (!is_storage_initialized)
				{
					init_storage();
					is_storage_initialized = true;
				}

				if (strlen (argv[curr_arg]) > 2) {
					ptr = &argv[curr_arg][2];
				} else {
					if (curr_arg >= argc - 1) {
						printf ("%s used without define name", argv[curr_arg]);
						break;
					}
					
					ptr = argv[++curr_arg];
				}

				read_expr (&ptr, name, "=");

				define = add_define (strdup (name), NULL);
				if (*skip_whitespace (++ptr) != '\0')
					define->contents = strdup (ptr);
				else
					set_define (define, "1", 1, false);
				break;
			}
			case 'V':
			{
				char *line;
				
				//check for something after -V
				if (strlen(argv[curr_arg]) > 2) {
					line = &argv[curr_arg][2];
				} else {
					//if not lets fail
					if (curr_arg >= argc - 1) {
						printf ("%s used without a line to assemble\n", argv[curr_arg]);
						return EXIT_FATAL_ERROR;
					}
					line = argv[++curr_arg];
				}
				
				mode |= MODE_COMMANDLINE;
				curr_input_file = strdup("-v");
				input_contents = (char *) malloc (strlen(line) + 1 + 2);
				output_filename = change_extension (curr_input_file, "bin");
					
				strcpy(input_contents, line);
				strcat(input_contents, "\n");
				break;
			}
			default:
				{
#ifndef _TEST
#ifdef _WINDOWS
					printf ("Unrecognized option %s\n", argv[curr_arg]);
#ifdef SPASM_NG_ENABLE_COM
					FreeConsole();
					return _AtlModule.WinMain(SW_HIDE);
#endif
#endif
#else
					printf ("Unrecognized option %s\n", argv[curr_arg]);
#endif
				}
				
			}

		} else {
			//if it's not a flag, then it must be a filename
			if (curr_input_file && (curr_input_file != starting_input_file) && !output_filename)
				output_filename = strdup(argv[curr_arg]);
			else if ((!curr_input_file) || (curr_input_file == starting_input_file))
				curr_input_file = strdup(argv[curr_arg]);

		}
		curr_arg++;
	}

	// Update case sensitivity settings
	set_case_sensitive (case_sensitive);
	
	//check on filenames
	if (!(mode & MODE_COMMANDLINE) && curr_input_file == starting_input_file) {
		puts ("No input file specified");
		free(starting_input_file);
		return EXIT_FATAL_ERROR;
	}

	if (curr_input_file != starting_input_file) {
		free(starting_input_file);
	}

	if (!output_filename) {
		output_filename = change_extension (curr_input_file, "bin");
	}

	if (!is_storage_initialized)
	{
		init_storage();
		is_storage_initialized = true;
	}
	output_contents = (unsigned char *) malloc(output_buf_size);
	ClearSPASMErrorSessions();

	int error = run_assembly();

	free(output_filename);
	output_filename = NULL;
	if (curr_input_file) {
		free(curr_input_file);
		curr_input_file = NULL;
	}
	if (include_dirs) {
		list_free(include_dirs, true, NULL);
	}

	free(output_contents);
	output_contents = NULL;
	ClearSPASMErrorSessions();
	free_storage();

#ifdef _WINDOWS
	_CrtDumpMemoryLeaks();
	if (IsDebuggerPresent())
	{
		system("PAUSE");
	}
#endif

	return error;
}
Esempio n. 2
0
	STDMETHOD(Assemble)(VARIANT varInput, IStream **ppOutput)
	{
		mode = m_dwOptions;

		if (V_VT(&varInput) == VT_BSTR)
		{
			mode |= MODE_NORMAL | MODE_COMMANDLINE;
			mode &= ~MODE_LIST;

			if (m_fFirstAssembly)
			{
				init_storage();
			}

			CW2CT szInput(V_BSTR(&varInput));
			input_contents = strdup(szInput);

			curr_input_file = strdup("COM Interface");
		}
		else
		{
			mode &= ~MODE_COMMANDLINE;
			mode |= MODE_NORMAL;

			curr_input_file = strdup(m_bstrInputFile);
			output_filename = strdup(m_bstrOutputFile);

			if (!m_fFirstAssembly)
			{
				free_storage();
			}

			init_storage();
		}

		// Set up the include directories
		CComPtr<IUnknown> pEnumUnk;
		HRESULT hr = m_pDirectories->get__NewEnum(&pEnumUnk);

		CComQIPtr<IEnumVARIANT> pEnum = pEnumUnk;

		CComVariant varItem;
		ULONG ulFetched;

		while (pEnum->Next(1, &varItem, &ulFetched) == S_OK)
		{
			include_dirs = list_prepend(include_dirs, (char *) strdup(_bstr_t(V_BSTR(&varItem))));
		}

		AddDefines();

		int error = run_assembly();

		list_free(include_dirs, true, NULL);
		include_dirs = NULL;

		ClearSPASMErrorSessions();

		long assembled_size = out_ptr - output_contents;

		HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, assembled_size);
		unsigned char *streambuf = (unsigned char *)GlobalLock(hGlobal);
		memcpy(streambuf, output_contents, assembled_size);
		GlobalUnlock(hGlobal);

		CComPtr<IStream> pStream;
		hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
		ULARGE_INTEGER ul;
		ul.QuadPart = assembled_size;
		pStream->SetSize(ul);

		m_fFirstAssembly = FALSE;
		if (output_filename != NULL)
		{
			free(output_filename);
			output_filename = NULL;
		}
		if (curr_input_file)
		{
			free(curr_input_file);
			curr_input_file = NULL;
		}

		if (mode & MODE_COMMANDLINE)
		{
			free(input_contents);
			input_contents = NULL;
		}

		m_fLabelsAreValid = FALSE;
		return pStream->QueryInterface(ppOutput);
	}