/* * 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); }
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; } }
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; } }
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; }
/* 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; }
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; }
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; }
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; }
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; }
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); }