Example #1
0
/*
 * Inits label, define, and macro
 * storage tables
 */
void init_storage() {
	define_t *define;
	char* test ;

	define_table = hash_init (MAX_DEFINES, (HASH_REMOVE_CALLBACK) destroy_define_value);
	label_table = hash_init (MAX_LABELS, (HASH_REMOVE_CALLBACK) destroy_label_value);

	add_define (strdup ("SPASM"), NULL)->contents = strdup ("1");
	add_define (strdup ("SPASMVER"), NULL)->contents = strdup ("2");
	add_define (strdup ("__LINE"), NULL)->contents = strdup ("0");
	add_define (strdup ("__FILE"), NULL)->contents = strdup ("Init");
	add_define (strdup ("TRUE"), NULL)->contents = strdup ("1");
	add_define (strdup ("FALSE"), NULL)->contents = strdup ("0");
	add_define (strdup ("__BM_SHD"), NULL)->contents = strdup ("2");
	add_define (strdup ("__BM_MSK_RGB"), NULL)->contents = strdup ("RGB(0, 255, 0)");

	(define = add_define (strdup ("RGB"), NULL))->contents = strdup ("((__R) << 16)|((__G) << 8)|(__B)");
	test = strdup ("__R,__G,__B)");
	parse_arg_defs (test, define);
	free(test);
	
	(define = add_define (strdup ("GETC"), NULL))->contents = strdup ("(0)");
	test = strdup ("__A, __N)"); 
	parse_arg_defs (test, define);
	free(test);
}
Example #2
0
STDMETHODIMP CZ80Assembler::AddDefine(BSTR bstrName, VARIANT varValue)
{
	if (V_VT(&varValue) == VT_EMPTY || V_VT(&varValue) == VT_ERROR)
	{
		V_VT(&varValue) = VT_UI4;
		V_UI4(&varValue) = 1;
	}

	VARIANT varDefine;
	VariantInit(&varDefine);
	V_VT(&varDefine) = VT_BSTR;
	V_BSTR(&varDefine) = SysAllocString(L"");
	HRESULT hr = VariantChangeType(&varDefine, &varValue, 0, VT_BSTR);
	if (FAILED(hr))
	{
		return hr;
	}

	CW2A szName(bstrName);

	bool fRedefined = false;
	define_t *define = add_define(strdup(szName), &fRedefined);

	if (define != NULL)
	{
		CW2A szContents(V_BSTR(&varDefine));
		define->contents = strdup(szContents);
		return S_OK;
	}
	else
	{
		return E_FAIL;
	}
}
Example #3
0
void set_define (define_t *define, const char *str, int len, bool redefined) {
	//if there's any possibility that the define is being redefined, use
	// this function to avoid memory leaks and infinite recursion,
	// otherwise writing directly to define->contents is fine

	if (!redefined || !define->contents) {
		//just set the contents
		if (define->contents)
			free (define->contents);

		define->contents = (len == -1 ? strdup (str) : strndup (str, len));

	} else {
		char *result, *temp;
		hash_t *old_list = define_table;
		list_t *old_arg_list = arg_list;
		//arg_list = NULL;

		define_table = hash_init (1, (HASH_REMOVE_CALLBACK) destroy_define_value);
		
		add_define (strdup (define->name), NULL, false)->contents = strdup (define->contents);
		temp = len == -1 ? strdup (str) : strndup (str, len);
		result = expand_expr (temp, false);
		free(temp);

		if (define->contents != NULL)
			free(define->contents);
		define->contents = result;

		hash_free(define_table);
		define_table = old_list;
		arg_list = old_arg_list;
	}
}
Example #4
0
static int
process_directive(gmx_cpp_t *handlep, const char *dname, const char *dval)
{
    gmx_cpp_t    handle = (gmx_cpp_t)*handlep;
    int          i, i0, len, status;
    unsigned int i1;
    char        *inc_fn, *name;
    const char  *ptr;
    int          bIfdef, bIfndef;

    /* #ifdef or ifndef statement */
    bIfdef  = (strcmp(dname, "ifdef") == 0);
    bIfndef = (strcmp(dname, "ifndef") == 0);
    if (bIfdef || bIfndef)
    {
        if ((handle->nifdef > 0) && (handle->ifdefs[handle->nifdef-1] != eifTRUE))
        {
            handle->nifdef++;
            srenew(handle->ifdefs, handle->nifdef);
            handle->ifdefs[handle->nifdef-1] = eifIGNORE;
        }
        else
        {
            snew(name, strlen(dval)+1);
            sscanf(dval, "%s", name);
            for (i = 0; (i < ndef); i++)
            {
                if (strcmp(defs[i].name, name) == 0)
                {
                    break;
                }
            }
            handle->nifdef++;
            srenew(handle->ifdefs, handle->nifdef);
            if ((bIfdef && (i < ndef)) || (bIfndef && (i == ndef)))
            {
                handle->ifdefs[handle->nifdef-1] = eifTRUE;
            }
            else
            {
                handle->ifdefs[handle->nifdef-1] = eifFALSE;
            }
            sfree(name);
        }
        return eCPP_OK;
    }

    /* #else statement */
    if (strcmp(dname, "else") == 0)
    {
        if (handle->nifdef <= 0)
        {
            return eCPP_SYNTAX;
        }
        if (handle->ifdefs[handle->nifdef-1] == eifTRUE)
        {
            handle->ifdefs[handle->nifdef-1] = eifFALSE;
        }
        else if (handle->ifdefs[handle->nifdef-1] == eifFALSE)
        {
            handle->ifdefs[handle->nifdef-1] = eifTRUE;
        }
        return eCPP_OK;
    }

    /* #endif statement */
    if (strcmp(dname, "endif") == 0)
    {
        if (handle->nifdef <= 0)
        {
            return eCPP_SYNTAX;
        }
        handle->nifdef--;
        return eCPP_OK;
    }

    /* Check whether we're not ifdeffed out. The order of this statement
       is important. It has to come after #ifdef, #else and #endif, but
       anything else should be ignored. */
    if (is_ifdeffed_out(handle))
    {
        return eCPP_OK;
    }

    /* Check for include statements */
    if (strcmp(dname, "include") == 0)
    {
        len = -1;
        i0  = 0;
        for (i1 = 0; (i1 < strlen(dval)); i1++)
        {
            if ((dval[i1] == '"') || (dval[i1] == '<') || (dval[i1] == '>'))
            {
                if (len == -1)
                {
                    i0  = i1+1;
                    len = 0;
                }
                else
                {
                    break;
                }
            }
            else if (len >= 0)
            {
                len++;
            }
        }
        if (len == -1)
        {
            return eCPP_SYNTAX;
        }
        snew(inc_fn, len+1);
        strncpy(inc_fn, dval+i0, len);
        inc_fn[len] = '\0';

        if (debug)
        {
            fprintf(debug, "Going to open include file '%s' i0 = %d, strlen = %d\n",
                    inc_fn, i0, len);
        }
        /* Open include file and store it as a child in the handle structure */
        status = cpp_open_file(inc_fn, &(handle->child), NULL);
        sfree(inc_fn);
        if (status != eCPP_OK)
        {
            handle->child = NULL;
            return status;
        }
        /* Make a linked list of open files and move on to the include file */
        handle->child->parent = handle;
        *handlep              = handle->child;
        handle                = *handlep;
        return eCPP_OK;
    }

    /* #define statement */
    if (strcmp(dname, "define") == 0)
    {
        /* Split it into name and value. */
        ptr = dval;
        while ((*ptr != '\0') && !isspace(*ptr))
        {
            ptr++;
        }
        name = gmx_strndup(dval, ptr - dval);

        while ((*ptr != '\0') && isspace(*ptr))
        {
            ptr++;
        }

        add_define(name, ptr);
        sfree(name);
        return eCPP_OK;
    }

    /* #undef statement */
    if (strcmp(dname, "undef") == 0)
    {
        snew(name, strlen(dval)+1);
        sscanf(dval, "%s", name);
        for (i = 0; (i < ndef); i++)
        {
            if (strcmp(defs[i].name, name) == 0)
            {
                sfree(defs[i].name);
                sfree(defs[i].def);
                break;
            }
        }
        sfree(name);
        for (; (i < ndef-1); i++)
        {
            defs[i].name = defs[i+1].name;
            defs[i].def  = defs[i+1].def;
        }
        ndef--;

        return eCPP_OK;
    }

    /* If we haven't matched anything, this is an unknown directive */
    return eCPP_SYNTAX;
}
Example #5
0
/* Open the file to be processed. The handle variable holds internal
   info for the cpp emulator. Return integer status */
int cpp_open_file(const char *filenm, gmx_cpp_t *handle, char **cppopts)
{
    gmx_cpp_t    cpp;
    char        *buf, *pdum;
    char        *ptr, *ptr2;
    int          i;
    unsigned int i1;

    /* First process options, they might be necessary for opening files
       (especially include statements). */
    i  = 0;
    if (cppopts)
    {
        while (cppopts[i])
        {
            if (strstr(cppopts[i], "-I") == cppopts[i])
            {
                add_include(cppopts[i]+2);
            }
            if (strstr(cppopts[i], "-D") == cppopts[i])
            {
                /* If the option contains a =, split it into name and value. */
                ptr = strchr(cppopts[i], '=');
                if (ptr)
                {
                    buf = gmx_strndup(cppopts[i] + 2, ptr - cppopts[i] - 2);
                    add_define(buf, ptr + 1);
                    sfree(buf);
                }
                else
                {
                    add_define(cppopts[i] + 2, NULL);
                }
            }
            i++;
        }
    }
    if (debug)
    {
        fprintf(debug, "GMXCPP: added %d command line arguments\n", i);
    }

    snew(cpp, 1);
    *handle      = cpp;
    cpp->fn      = NULL;
    /* Find the file. First check whether it is in the current directory. */
    if (gmx_fexist(filenm))
    {
        cpp->fn = gmx_strdup(filenm);
    }
    else
    {
        /* If not, check all the paths given with -I. */
        for (i = 0; i < nincl; ++i)
        {
            snew(buf, strlen(incl[i]) + strlen(filenm) + 2);
            sprintf(buf, "%s/%s", incl[i], filenm);
            if (gmx_fexist(buf))
            {
                cpp->fn = buf;
                break;
            }
            sfree(buf);
        }
        /* If still not found, check the Gromacs library search path. */
        if (!cpp->fn)
        {
            cpp->fn = low_gmxlibfn(filenm, FALSE, FALSE);
        }
    }
    if (!cpp->fn)
    {
        gmx_fatal(FARGS, "Topology include file \"%s\" not found", filenm);
    }
    if (NULL != debug)
    {
        fprintf(debug, "GMXCPP: cpp file open %s\n", cpp->fn);
    }
    /* If the file name has a path component, we need to change to that
     * directory. Note that we - just as C - always use UNIX path separators
     * internally in include file names.
     */
    ptr  = strrchr(cpp->fn, '/');
    ptr2 = strrchr(cpp->fn, DIR_SEPARATOR);

    if (ptr == NULL || (ptr2 != NULL && ptr2 > ptr))
    {
        ptr = ptr2;
    }
    if (ptr == NULL)
    {
        cpp->path = NULL;
        cpp->cwd  = NULL;
    }
    else
    {
        cpp->path = cpp->fn;
        *ptr      = '\0';
        cpp->fn   = gmx_strdup(ptr+1);
        snew(cpp->cwd, STRLEN);

        gmx_getcwd(cpp->cwd, STRLEN);
        if (NULL != debug)
        {
            fprintf(debug, "GMXCPP: cwd %s\n", cpp->cwd);
        }
        gmx_chdir(cpp->path);

        if (NULL != debug)
        {
            fprintf(debug, "GMXCPP: chdir to %s\n", cpp->path);
        }
    }
    cpp->line_len = 0;
    cpp->line     = NULL;
    cpp->line_nr  = 0;
    cpp->nifdef   = 0;
    cpp->ifdefs   = NULL;
    cpp->child    = NULL;
    cpp->parent   = NULL;
    if (cpp->fp == NULL)
    {
        if (NULL != debug)
        {
            fprintf(debug, "GMXCPP: opening file %s\n", cpp->fn);
        }
        cpp->fp = fopen(cpp->fn, "r");
    }
    if (cpp->fp == NULL)
    {
        switch (errno)
        {
            case EINVAL:
            default:
                return eCPP_UNKNOWN;
        }
    }
    return eCPP_OK;
}
Example #6
0
static void
handle_define(char *yyt)
{
    char namebuf[NSIZE];
    char args[NARGS][NSIZE];
    char mtext[MLEN];
    char *p, *q;

    p = yyt;
    (void)strcat(p, " ");
    q = namebuf;
    GETALPHA(p, q, namebuf+NSIZE-1);
    if (*p == '(')
    {       /* if "function macro" */
	int arg;
	int inid;
	char *ids = 0;
	p++;            /* skip '(' */
	SKIPWHITE;
	if (*p == ')')
	{
	    arg = 0;
	}
	else
	{
	    for (arg = 0; arg < NARGS; )
	    {
		q = args[arg];
		GETALPHA(p, q, args[arg] + NSIZE - 1);
		arg++;
		SKIPWHITE;
		if (*p == ')')
		    break;
		if (*p++ != ',')
		{
		    lexerror("Missing ',' in #define parameter list");
		    return;
		}
		SKIPWHITE;
	    }
	    if (arg == NARGS)
	    {
		lexerror("Too many macro arguments");
		return;
	    }
	}
	p++;            /* skip ')' */
	for (inid = 0, q = mtext; *p; )
	{
	    if (isalunum(*p))
	    {
		if (!inid)
		{
		    inid++;
		    ids = p;
		}
	    }
	    else
	    {
		if (inid)
		{
		    size_t l, idlen = p - ids;
		    int n;
		    
		    for (n = 0; n < arg; n++)
		    {
			l = strlen(args[n]);
			if (l == idlen && strncmp(args[n], ids, l) == 0)
			{
			    q -= idlen;
			    *q++ = MARKS;
			    *q++ = n+MARKS+1;
			    break;
			}
		    }
		    inid = 0;
		}
	    }
	    *q = *p;
	    if (*p++ == MARKS)
		*++q = MARKS;
	    if (q < mtext + MLEN - 2)
		q++;
	    else
	    {
		lexerror("Macro text too long");
		return;
	    }
	    if (!*p && p[-2] == '\\')
	    {
		q -= 2;
		refill();
		p = yytext;
	    }
	}
	*--q = 0;
	add_define(namebuf, arg, mtext);
    }
    else
    {
	for (q = mtext; *p; )
	{
	    *q = *p++;
	    if (q < mtext + MLEN - 2)
		q++;
	    else
	    {
		lexerror("Macro text too long");
		return;
	    }
	    if (!*p && p[-2] == '\\')
	    {
		q -= 2;
		refill();
		p = yytext;
	    }
	}
	*--q = 0;
	add_define(namebuf, -1, mtext);
    }
    return;
}
Example #7
0
void
start_new_file(FILE *f)
{
    struct lpc_predef_s *tmpf;
    free_defines();
    add_define("_FUNCTION", -1, "");
    add_define("LPC4", -1, "");   /* Tell coders this is LPC ver 4.0 */
    add_define("CD_DRIVER", -1, "");
#ifdef DEBUG
    add_define("DEBUG_DRIVER", -1, "");
#endif
    add_define("T_INTEGER" , -1, ltoa(T_NUMBER));
    add_define("T_FLOAT"   , -1, ltoa(T_FLOAT));
    add_define("T_STRING"  , -1, ltoa(T_STRING));
    add_define("T_OBJECT"  , -1, ltoa(T_OBJECT));
    add_define("T_FUNCTION", -1, ltoa(T_FUNCTION));
    add_define("T_ARRAY"   , -1, ltoa(T_POINTER));
    add_define("T_MAPPING" , -1, ltoa(T_MAPPING));

    for (tmpf = lpc_predefs; tmpf; tmpf = tmpf->next) 
    {
	char namebuf[NSIZE];
	char mtext[MLEN];
	
	*mtext='\0';
	(void)sscanf(tmpf->flag, "%[^=]=%[ -~=]", namebuf, mtext);
	if (strlen(namebuf) >= NSIZE)
	    fatal("NSIZE exceeded\n");
	if (strlen(mtext) >= MLEN)
	    fatal("MLEN exceeded\n");
	add_define(namebuf,-1,mtext);
    }
    keep1.token = keep2.token = keep3.token = -47;
    yyin = f;
    slast = '\n';
    lastchar = '\n';
    inctop = 0;         /* If not here, where? */
    num_incfiles = 0;
    current_incfile = 0;
    current_line = 1;
    lex_fatal = 0;
    incdepth = 0;
    nbuf = 0;
    outp = defbuf+DEFMAX;
    pragma_strict_types = 0;        
    pragma_no_inherit = pragma_no_clone = pragma_no_shadow = pragma_resident = 0;
    nexpands = 0;
}
Example #8
0
char *handle_directive (const char *ptr) {
	static const char *dirs[] = {"db", "dw", "end", "org", "byte", "word", "fill", "block", "addinstr",
		"echo", "error", "list", "nolist", "equ", "show", "option", "seek", "assume", "dl", "long", NULL};
	char name_buf[32];
	int dir;

	//same deal as handle_preop, just with directives instead
	bool valid_directive = false;
	unsigned name_len = 0;
	while (ptr[name_len] != 0 && !isspace(ptr[name_len])) {
		name_len++;
	}

	// If longer than name_buf, it can't be a valid directive.
	if (name_len < sizeof(name_buf)) {
		// Copy string for comparing against
		memcpy(name_buf, ptr, name_len);
		name_buf[name_len] = 0;

		dir = 0;
		while (dirs[dir]) {
			if (!strcasecmp(dirs[dir], name_buf)) {
				valid_directive = true;
				break;
			}
			dir++;
		}
	}

	if (!valid_directive)
		return handle_opcode_or_macro ((char *) ptr - 1);

	ptr = skip_whitespace(&ptr[name_len]);

	switch (dir) {
		case 0: //DB
		case 4: //BYTE
		{
			ptr = parse_emit_string (ptr, ES_BYTE, NULL);
			break;
		}
		case 1: //DW
		case 5: //WORD
		{
			ptr = parse_emit_string (ptr, ES_WORD, NULL);
			break;
		}
		case 18: //DL
		case 19: //LONG
		{
			ptr = parse_emit_string (ptr, ES_LONG, NULL);
			break;
		}
		case 3: //ORG
		{
			int value;
			char value_str[256] = "";
			bool fResult = read_expr(&ptr, value_str, "");
			if (fResult == true)
			{
				if (parse_num(value_str, &value) == true)
				{
					if (value < 0)
					{
						SetLastSPASMError(SPASM_ERR_INVALID_ADDRESS, skip_whitespace(value_str));
					}
					else
					{
						program_counter = value;
					}
				}
			}
			if ((fResult == false) || (strlen(skip_whitespace(value_str)) == 0))
			{
				SetLastSPASMError(SPASM_ERR_VALUE_EXPECTED);
			}
			break;
		}
		case 6: //FILL
		case 7: //BLOCK
		{
			int size, fill_value;
			char szSize[256], szFill[256];
			bool old_listing_on = listing_on;
			//listing_on = false;

			read_expr (&ptr, szSize, ",");
			parse_num (szSize, &size);
			ptr = skip_whitespace (ptr);
			if (*ptr == ',')
				ptr++;

			if (read_expr (&ptr, szFill, "")) {
				//if there's a value to fill the block with, then handle that
				parse_num (szFill, &fill_value);
			} else {
				//otherwise use 0
				fill_value = 0;
			}

			if (size < 0) {
				SetLastSPASMError(SPASM_ERR_SIZE_MUST_BE_POSITIVE, szSize);
				listing_on = old_listing_on;
				break;
			}

			if (fill_value < -128 || fill_value > 255)
			{
				SetLastSPASMWarning(SPASM_WARN_TRUNCATING_8);
			}

			program_counter += size;
			stats_datasize += size;

			while (size-- > 0)
				write_out (fill_value & 0xFF);

			//listing_on = old_listing_on;
			break;
		}
		case 8: //ADDINSTR
		{
			instr *instr = (struct _instr *) malloc (sizeof (struct _instr));
			char word[256];
			int result;
			char *mnemonic;
			size_t i, base = 0, size_left;
			int j;
			opcode *last_opcode = NULL, *curr_opcode = all_opcodes, *new_opcode;

			memset (instr, 0, sizeof (struct _instr));

			// Mnemonic
			if (!read_expr (&ptr, word, " \t")) goto addinstr_fail;
			mnemonic = strdup (word);

			// Args
			if (!read_expr (&ptr, word, " \t")) goto addinstr_fail;
			reduce_string (word);
			instr->args = strdup (word);

			// Instruction data
			if (!read_expr (&ptr, word, " \t")) goto addinstr_fail;
	        conv_hex (word, word + strlen (word), &result);
	        instr->instr_size = strlen (word) / 2;

	        for (j = instr->instr_size - 1; j >= 0; j--)
	        	instr->instr_data[instr->instr_size - j - 1] = (result >> (j * 8)) & 0xFF;


			// Size
			if (!read_expr (&ptr, word, " \t")) goto addinstr_fail;
			if (!parse_num (word, &instr->size)) goto addinstr_fail;

			// Class
			read_expr (&ptr, word, " \t");

			// Extended
			read_expr (&ptr, word, " \t");

			// End data ...
			if (read_expr (&ptr, word, " \t")) {
				int output;
				conv_hex (word, word + strlen (word), &output);
				instr->end_data = (unsigned char) output;
				instr->has_end_data = true;
			}

			size_left = instr->size - instr->instr_size;
			while ((i = strcspn (&instr->args[base], "*")) + base != strlen (instr->args)) {
				switch (size_left - instr->has_end_data) {
					case 2:	((char *) instr->args)[base+i] = '*'; break;
					case 1: ((char *) instr->args)[base+i] = '&'; break;
					default:
						((char *) instr->args)[base+i] = '&'; break;
						//show_error ("Invalid wildcard type in ADDRINSTR");
						//goto addinstr_fail;
						break;
				}
				size_left -= 2;
				base += i + 1;
			}

			new_opcode = (opcode *)  malloc (sizeof (opcode));
			new_opcode->name = mnemonic;
			new_opcode->num_instrs = 1;
			new_opcode->use_count = 0;
			new_opcode->instrs = instr;
			new_opcode->is_added = true;

			while (curr_opcode) {
				if (strcasecmp (mnemonic, curr_opcode->name) == 0)
					break;
				last_opcode = curr_opcode;
				curr_opcode = curr_opcode->next;
			}

			if (curr_opcode == NULL) {
				last_opcode->next = new_opcode;
				new_opcode->next = NULL;
			} else {
				new_opcode->next = curr_opcode;
				if (last_opcode)
					last_opcode->next = new_opcode;
				else
					all_opcodes = new_opcode;
			}

			// You can ignore class, etc
			ptr = skip_to_line_end (ptr);
			break;
addinstr_fail:
			SetLastSPASMError(SPASM_ERR_INVALID_ADDINSTR);
			if (instr && instr->args) free ((void *) instr->args);
			if (instr) free (instr);
			ptr = skip_to_line_end(ptr);
			break;
		}
		case 9: //ECHO
		{
			if (ptr[0] == '>')
			{
				char target_format[2] = "w";
				FILE *echo_target;
				char filename[MAX_PATH];
				char temp_filename[MAX_PATH];
				define_t *define;

				if ((++ptr)[0] == '>')
					target_format[0] = 'a';

				ptr = skip_whitespace (ptr + 1);
				if (is_end_of_code_line (ptr)) {
					SetLastSPASMError(SPASM_ERR_FILENAME_EXPECTED);
					return NULL;
				}

				read_expr (&ptr, filename, " \t");

				// Is the filename given a macro?
				if ((define = search_defines (filename)))
					strncpy (filename, skip_whitespace(define->contents), sizeof (filename));
					
				reduce_string(filename);

				if (is_abs_path(filename)) {
					strncpy(temp_filename, skip_whitespace (filename), sizeof (temp_filename));
				} else {
					strncpy(temp_filename, temp_path, sizeof (temp_filename));
					strncat(temp_filename, "/", sizeof (temp_filename) - 1);
					strncat(temp_filename, skip_whitespace (filename), sizeof (temp_filename) - 1);
				}
				echo_target = fopen (fix_filename (temp_filename), target_format);
				if (echo_target == NULL) {
					SetLastSPASMError(SPASM_ERR_NO_ACCESS, filename);
					return NULL;
				}

				//if the output's redirected to a file, process it now
				WORD orig_attributes = save_console_attributes();
				set_console_attributes (COLOR_GREEN);
				ptr = parse_emit_string (ptr, ES_ECHO, echo_target);
				restore_console_attributes(orig_attributes);
			} else {
				char expr[256];
				read_expr (&ptr, expr, "");

				// If it craps out for some reason, save it for the next pass
				int session = StartSPASMErrorSession();
				parse_emit_string (expr, ES_ECHO, NULL);

				if (IsSPASMErrorSessionFatal(session) == true)
				{
					add_pass_two_output (expr, OUTPUT_ECHO);
				}
				else if (GetSPASMErrorSessionErrorCount(session) > 0)
				{
					WORD orig_attributes = save_console_attributes();
					set_console_attributes(COLOR_GREEN);
					int internal_session = StartSPASMErrorSession();
					parse_emit_string (expr, ES_ECHO, stdout);
					restore_console_attributes(orig_attributes);
					EndSPASMErrorSession(internal_session);

					ReplaySPASMErrorSession(session);
				}
				else
				{
					expand_buf_t *echo = eb_init(256);
					parse_emit_string (expr, ES_FCREATE, echo);

					char *echo_string = eb_extract(echo);
					eb_free(echo);

					char *expanded_string = escape_string(echo_string);
					free(echo_string);

					add_pass_two_output (expanded_string, OUTPUT_ECHO);
					free(expanded_string);
				}
				EndSPASMErrorSession(session);
			}
			break;
		}
		case 10: //ERROR
		{
			expand_buf_t *eb = eb_init(64);
			ptr = parse_emit_string(ptr, ES_FCREATE, eb);

			char *error_str = eb_extract(eb);
			eb_free(eb);

			SetLastSPASMError(SPASM_ERR_CUSTOM, error_str);
			free(error_str);
			break;
		}
		case 11: //LIST
		{
			//if listing was off already, then the listing
			// for the start of this line wouldn't have been
			// written, so make sure the end doesn't get
			// written either
			if (!listing_on)
				listing_for_line_done = true;
			listing_on = true;
			break;
		}
		case 12: //NOLIST
		{
			//if listing is on, then it would've written
			// the starting stuff for this line already,
			// so take that out
			if ((mode & MODE_LIST) && listing_on)
				listing_offset -= 14;
			listing_on = false;
			break;
		}
		case 13: //EQU
		{
			// Finally, a proper .equ!
			int value;
			char value_str[256];

			read_expr (&ptr, value_str, "");
			if (!parse_num (value_str, &value) && parser_forward_ref_err) {
			} else {
				if (last_label == NULL)
					SetLastSPASMError(SPASM_ERR_EQUATE_MISSING_LABEL);
				else
					last_label->value = value;
			}
			break;
		}
		case 14: //SHOW
		{
			char name[256];
			define_t *define;

			//get the name
			read_expr (&ptr, name, "");
			define = search_defines (name);
			if (define == NULL) {
				//if it doesn't exist yet, save it for the second pass
				add_pass_two_output (name, OUTPUT_SHOW);
			} else {
				//otherwise, show it now
				show_define (define);
			}
			break;
		}
		case 15: //OPTION
		{
			char *word = NULL;
			arg_context_t context = ARG_CONTEXT_INITIALIZER;
			while ((word = extract_arg_string(&ptr, &context)) != NULL)
			{
				char name[256], *expr = word;
				char *define_name;
				define_t *define;

				read_expr(&expr, name, "=");
				if (*expr == '=')
				{
					expr++;
				}
				
				if (!(isalpha(name[0]))) {
					SetLastSPASMError(SPASM_ERR_INVALID_OPTION, name);
					return (char *) ptr;
				}
				
				if (is_end_of_code_line (skip_whitespace (expr)))
					expr = strdup ("1");
				else {
					//if (!parse_num (expr, NULL))
					//	return NULL;
					expr = strdup (expr);
				}

				if (strlen (name) == 0) {
					show_error ("Invalid option statement");
					return NULL;
				}

				define_name = (char *) malloc (strlen (name) + 3);
				strcat (strcpy (define_name, "__"), name);

				define = add_define (define_name, NULL);
				set_define (define, expr, -1, false);
				free(expr);
			}
			break;
		}
		case 16: //SEEK
		{
			int value;
			char value_str[256];

			read_expr (&ptr, value_str, "");
			parse_num (value_str, (int *) &value);

			//printf("value_str: %s\npc: %d\n", value_str, program_counter);

			if (value > program_counter && (value - program_counter > output_buf_size - (out_ptr - output_contents)))
				show_fatal_error ("Seek location %d out of bounds", value);
			else if (value < program_counter && (value - (int) program_counter + (out_ptr - output_contents) < 0))
				show_fatal_error ("Seek value %d too small", value);
		
			out_ptr += value - ((int) program_counter);
			//printf("base: %p; ptr: %p\n", output_contents, out_ptr);
			program_counter = value;
			break;
		}
		case 17: //ASSUME
		{
			char args[256];
			read_expr(&ptr, args, "");

			char word[256];
			char *value_str = args;
			read_expr(&value_str, word, "=");

			int value = 1;
			bool success = true;
			if (*value_str == '=') {
				success = parse_num(value_str+1, &value);
			}

			if (!(mode & MODE_EZ80) || strcasecmp(word, "adl") || !success) {
				SetLastSPASMError(SPASM_ERR_INVALID_OPTION, args);
				return (char *)ptr;
			}

			adl_mode = (value != 0);
			break;
		}
	}

	return (char *) ptr;
}
Example #9
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;
}
Example #10
0
int main(int argc, char *argv[])
{
   string     cfg_file;
   const char *parsed_file = NULL;
   const char *source_file = NULL;
   const char *output_file = NULL;
   const char *source_list = NULL;
   log_mask_t mask;
   int        idx;
   const char *p_arg;

   /* If ran without options... check keyword sort and show the usage info */
   if (argc == 1)
   {
      keywords_are_sorted();
      usage_exit(NULL, argv[0], EXIT_SUCCESS);
   }

   /* Build options map */
   register_options();

   Args arg(argc, argv);

   if (arg.Present("--version") || arg.Present("-v"))
   {
      version_exit();
   }
   if (arg.Present("--help") || arg.Present("-h") ||
       arg.Present("--usage") || arg.Present("-?"))
   {
      usage_exit(NULL, argv[0], EXIT_SUCCESS);
   }

   if (arg.Present("--show-config"))
   {
      print_options(stdout, true);
      return(0);
   }

#ifdef WIN32
   /* tell windoze not to change what I write to stdout */
   (void)_setmode(_fileno(stdout), _O_BINARY);
#endif

   /* Init logging */
   log_init(stderr);
   if (arg.Present("-q"))
   {
      logmask_from_string("", mask);
      log_set_mask(mask);
   }
   if (((p_arg = arg.Param("-L")) != NULL) ||
       ((p_arg = arg.Param("--log")) != NULL))
   {
      logmask_from_string(p_arg, mask);
      log_set_mask(mask);
   }
   cpd.frag = arg.Present("--frag");

   if ((p_arg = arg.Param("--decode")) != NULL)
   {
      log_pcf_flags(LSYS, strtoul(p_arg, NULL, 16));
      exit(EXIT_SUCCESS);
   }

   /* Get the config file name */
   if (((p_arg = arg.Param("--config")) != NULL) ||
       ((p_arg = arg.Param("-c")) != NULL))
   {
      cfg_file = p_arg;
   }

   /* Try to file a config at an alternate location */
   if (cfg_file.empty())
   {
      if (!unc_getenv("UNCRUSTIFY_CONFIG", cfg_file))
      {
         string home;

         if (unc_homedir(home))
         {
            struct stat tmp_stat;
            string      path;

            path = home + "/uncrustify.cfg";
            if (stat(path.c_str(), &tmp_stat) == 0)
            {
               cfg_file = path;
            }
            else
            {
               path = home + "/.uncrustify.cfg";
               if (stat(path.c_str(), &tmp_stat) == 0)
               {
                  cfg_file = path;
               }
            }
         }
      }
   }

   /* Get the parsed file name */
   if (((parsed_file = arg.Param("--parsed")) != NULL) ||
       ((parsed_file = arg.Param("-p")) != NULL))
   {
      LOG_FMT(LNOTE, "Will export parsed data to: %s\n", parsed_file);
   }

   /* Enable log sevs? */
   if (arg.Present("-s") || arg.Present("--show"))
   {
      log_show_sev(true);
   }

   /* Load the config file */
   set_option_defaults();

   /* Load type files */
   idx = 0;
   while ((p_arg = arg.Params("-t", idx)) != NULL)
   {
      load_keyword_file(p_arg);
   }

   /* add types */
   idx = 0;
   while ((p_arg = arg.Params("--type", idx)) != NULL)
   {
      add_keyword(p_arg, CT_TYPE);
   }

   /* Load define files */
   idx = 0;
   while ((p_arg = arg.Params("-d", idx)) != NULL)
   {
      load_define_file(p_arg);
   }

   /* add defines */
   idx = 0;
   while ((p_arg = arg.Params("--define", idx)) != NULL)
   {
      add_define(p_arg, NULL);
   }

   /* Check for a language override */
   if ((p_arg = arg.Param("-l")) != NULL)
   {
      cpd.lang_flags = language_from_tag(p_arg);
      if (cpd.lang_flags == 0)
      {
         LOG_FMT(LWARN, "Ignoring unknown language: %s\n", p_arg);
      }
      else
      {
         cpd.lang_forced = true;
      }
   }

   /* Get the source file name */
   if (((source_file = arg.Param("--file")) == NULL) &&
       ((source_file = arg.Param("-f")) == NULL))
   {
      // not using a single file, source_file is NULL
   }

   if (((source_list = arg.Param("--files")) == NULL) &&
       ((source_list = arg.Param("-F")) == NULL))
   {
      // not using a file list, source_list is NULL
   }

   const char *prefix = arg.Param("--prefix");
   const char *suffix = arg.Param("--suffix");

   bool no_backup        = arg.Present("--no-backup");
   bool replace          = arg.Present("--replace");
   bool keep_mtime       = arg.Present("--mtime");
   bool update_config    = arg.Present("--update-config");
   bool update_config_wd = arg.Present("--update-config-with-doc");
   bool detect           = arg.Present("--detect");

   /* Grab the output override */
   output_file = arg.Param("-o");

   LOG_FMT(LDATA, "config_file = %s\n", cfg_file.c_str());
   LOG_FMT(LDATA, "output_file = %s\n", (output_file != NULL) ? output_file : "null");
   LOG_FMT(LDATA, "source_file = %s\n", (source_file != NULL) ? source_file : "null");
   LOG_FMT(LDATA, "source_list = %s\n", (source_list != NULL) ? source_list : "null");
   LOG_FMT(LDATA, "prefix      = %s\n", (prefix != NULL) ? prefix : "null");
   LOG_FMT(LDATA, "suffix      = %s\n", (suffix != NULL) ? suffix : "null");
   LOG_FMT(LDATA, "replace     = %d\n", replace);
   LOG_FMT(LDATA, "no_backup   = %d\n", no_backup);
   LOG_FMT(LDATA, "detect      = %d\n", detect);

   if (replace || no_backup)
   {
      if ((prefix != NULL) || (suffix != NULL))
      {
         usage_exit("Cannot use --replace with --prefix or --suffix", argv[0], 66);
      }
      if ((source_file != NULL) || (output_file != NULL))
      {
         usage_exit("Cannot use --replace or --no-backup with -f or -o", argv[0], 66);
      }
   }
   else
   {
      if ((prefix == NULL) && (suffix == NULL))
      {
         suffix = ".uncrustify";
      }
   }

   /* Try to load the config file, if available.
    * It is optional for "--universalindent" and "--detect", but required for
    * everything else.
    */
   if (!cfg_file.empty())
   {
      cpd.filename = cfg_file.c_str();
      if (load_option_file(cpd.filename) < 0)
      {
         usage_exit("Unable to load the config file", argv[0], 56);
      }
   }

   if (arg.Present("--universalindent"))
   {
      FILE *pfile = stdout;

      if (output_file != NULL)
      {
         pfile = fopen(output_file, "w");
         if (pfile == NULL)
         {
            fprintf(stderr, "Unable to open %s for write: %s (%d)\n",
                    output_file, strerror(errno), errno);
            return(EXIT_FAILURE);
         }
      }

      print_universal_indent_cfg(pfile);

      return(EXIT_SUCCESS);
   }

   if (detect)
   {
      file_mem fm;

      if ((source_file == NULL) || (source_list != NULL))
      {
         fprintf(stderr, "The --detect option requires a single input file\n");
         return(EXIT_FAILURE);
      }

      /* Do some simple language detection based on the filename extension */
      if (!cpd.lang_forced || (cpd.lang_flags == 0))
      {
         cpd.lang_flags = language_from_filename(source_file);
      }

      /* Try to read in the source file */
      if (load_mem_file(source_file, fm) < 0)
      {
         LOG_FMT(LERR, "Failed to load (%s)\n", source_file);
         cpd.error_count++;
         return(EXIT_FAILURE);
      }

      uncrustify_start(fm.data);
      detect_options();
      uncrustify_end();

      redir_stdout(output_file);
      save_option_file(stdout, update_config_wd);
      return(EXIT_SUCCESS);
   }

   /* Everything beyond this point requires a config file, so complain and
    * bail if we don't have one.
    */
   if (cfg_file.empty())
   {
      usage_exit("Specify the config file with '-c file' or set UNCRUSTIFY_CONFIG",
                 argv[0], 58);
   }

   /*
    *  Done parsing args
    */

   if (update_config || update_config_wd)
   {
      redir_stdout(output_file);
      save_option_file(stdout, update_config_wd);
      return(0);
   }

   /* Check for unused args (ignore them) */
   idx   = 1;
   p_arg = arg.Unused(idx);

   /* Check args - for multifile options */
   if ((source_list != NULL) || (p_arg != NULL))
   {
      if (source_file != NULL)
      {
         usage_exit("Cannot specify both the single file option and a multi-file option.",
                    argv[0], 67);
      }

      if (output_file != NULL)
      {
         usage_exit("Cannot specify -o with a multi-file option.",
                    argv[0], 68);
      }
   }

   /* This relies on cpd.filename being the config file name */
   load_header_files();

   if ((source_file == NULL) && (source_list == NULL) && (p_arg == NULL))
   {
      /* no input specified, so use stdin */
      if (cpd.lang_flags == 0)
      {
         cpd.lang_flags = LANG_C;
      }

      redir_stdout(output_file);

      file_mem fm;
      if (!read_stdin(fm))
      {
         LOG_FMT(LERR, "Failed to read stdin\n");
         return(100);
      }

      cpd.filename = "stdin";

      /* Done reading from stdin */
      LOG_FMT(LSYS, "Parsing: %d bytes (%d chars) from stdin as language %s\n",
              (int)fm.raw.size(), (int)fm.data.size(),
              language_to_string(cpd.lang_flags));

      uncrustify_file(fm, stdout, parsed_file);
   }
   else if (source_file != NULL)
   {
      /* Doing a single file */
      do_source_file(source_file, output_file, parsed_file, no_backup, keep_mtime);
   }
   else
   {
      /* Doing multiple files */
      if (prefix != NULL)
      {
         LOG_FMT(LSYS, "Output prefix: %s/\n", prefix);
      }
      if (suffix != NULL)
      {
         LOG_FMT(LSYS, "Output suffix: %s\n", suffix);
      }

      /* Do the files on the command line first */
      idx = 1;
      while ((p_arg = arg.Unused(idx)) != NULL)
      {
         char outbuf[1024];
         do_source_file(p_arg,
                        make_output_filename(outbuf, sizeof(outbuf), p_arg, prefix, suffix),
                        NULL, no_backup, keep_mtime);
      }

      if (source_list != NULL)
      {
         process_source_list(source_list, prefix, suffix, no_backup, keep_mtime);
      }
   }

   clear_keyword_file();
   clear_defines();

   return((cpd.error_count != 0) ? 1 : 0);
}