static void test_Trim(TestBatchRunner *runner) { String *ws_smiley = S_smiley_with_whitespace(NULL); String *ws_foo = S_get_str(" foo "); String *ws_only = S_get_str(" \t \r\n"); String *trimmed = S_get_str("a b"); String *got; got = Str_Trim(ws_smiley); TEST_TRUE(runner, Str_Equals_Utf8(got, smiley, smiley_len), "Trim"); DECREF(got); got = Str_Trim_Top(ws_foo); TEST_TRUE(runner, Str_Equals_Utf8(got, "foo ", 5), "Trim_Top"); DECREF(got); got = Str_Trim_Tail(ws_foo); TEST_TRUE(runner, Str_Equals_Utf8(got, " foo", 5), "Trim_Tail"); DECREF(got); got = Str_Trim(ws_only); TEST_TRUE(runner, Str_Equals_Utf8(got, "", 0), "Trim with only whitespace"); DECREF(got); got = Str_Trim_Top(ws_only); TEST_TRUE(runner, Str_Equals_Utf8(got, "", 0), "Trim_Top with only whitespace"); DECREF(got); got = Str_Trim_Tail(ws_only); TEST_TRUE(runner, Str_Equals_Utf8(got, "", 0), "Trim_Tail with only whitespace"); DECREF(got); got = Str_Trim(trimmed); TEST_TRUE(runner, Str_Equals(got, (Obj*)trimmed), "Trim doesn't change trimmed string"); DECREF(got); got = Str_Trim_Top(trimmed); TEST_TRUE(runner, Str_Equals(got, (Obj*)trimmed), "Trim_Top doesn't change trimmed string"); DECREF(got); got = Str_Trim_Tail(trimmed); TEST_TRUE(runner, Str_Equals(got, (Obj*)trimmed), "Trim_Tail doesn't change trimmed string"); DECREF(got); DECREF(trimmed); DECREF(ws_only); DECREF(ws_foo); DECREF(ws_smiley); }
static void test_numbers(TestBatchRunner *runner) { Integer *i64 = Int_new(33); String *json = Json_to_json((Obj*)i64); String *trimmed = Str_Trim(json); TEST_TRUE(runner, Str_Equals_Utf8(trimmed, "33", 2), "Integer"); DECREF(json); DECREF(trimmed); Float *f64 = Float_new(33.33); json = Json_to_json((Obj*)f64); if (json) { double value = Str_To_F64(json); double diff = 33.33 - value; if (diff < 0.0) { diff = 0.0 - diff; } TEST_TRUE(runner, diff < 0.0001, "Float"); DECREF(json); } else { FAIL(runner, "Float conversion to json failed."); } DECREF(i64); DECREF(f64); }
static void test_escapes(TestBatchRunner *runner) { for (int i = 0; control_escapes[i] != NULL; i++) { String *string = Str_new_from_char(i); const char *escaped = control_escapes[i]; String *json = Json_to_json((Obj*)string); String *trimmed = Str_Trim(json); String *decoded = (String*)Json_from_json(json); String *json_wanted = Str_newf("\"%s\"", escaped); TEST_TRUE(runner, Str_Equals(json_wanted, (Obj*)trimmed), "encode control escape: %s", escaped); TEST_TRUE(runner, decoded != NULL && Str_Equals(string, (Obj*)decoded), "decode control escape: %s", escaped); DECREF(string); DECREF(json); DECREF(trimmed); DECREF(decoded); DECREF(json_wanted); } for (int i = 0; quote_escapes_source[i] != NULL; i++) { const char *source = quote_escapes_source[i]; const char *escaped = quote_escapes_json[i]; String *string = Str_new_from_utf8(source, strlen(source)); String *json = Json_to_json((Obj*)string); String *trimmed = Str_Trim(json); String *decoded = (String*)Json_from_json(json); String *json_wanted = Str_newf("\"%s\"", escaped); TEST_TRUE(runner, Str_Equals(json_wanted, (Obj*)trimmed), "encode quote/backslash escapes: %s", source); TEST_TRUE(runner, decoded != NULL && Str_Equals(string, (Obj*)decoded), "decode quote/backslash escapes: %s", source); DECREF(string); DECREF(json); DECREF(trimmed); DECREF(decoded); DECREF(json_wanted); } }
/** * Read a command line from the keyboard and return a pointer to the string. * Only string returned by this function can be given for it as argument! * The string will be stored into command history buffer. * @return Pointer to the string which should be given back to this * function or DebugUI_FreeCommand() for re-use/history. * Returns NULL when error occurred. */ static char *DebugUI_GetCommand(char *input) { /* Allow conditional parsing of the ~/.inputrc file. */ rl_readline_name = "Hatari"; /* Tell the completer that we want a crack first. */ rl_attempted_completion_function = DebugUI_Completion; DebugUI_FreeCommand(input); return Str_Trim(readline("> ")); }
/** * Load keyboard remap file */ void Keymap_LoadRemapFile(char *pszFileName) { char szString[1024]; int STScanCode, PCKeyCode; FILE *in; int idx = 0; /* Initialize table with default values */ memset(LoadedKeymap, 0, sizeof(LoadedKeymap)); if (!*pszFileName) return; /* Attempt to load file */ if (!File_Exists(pszFileName)) { Log_Printf(LOG_DEBUG, "Keymap_LoadRemapFile: '%s' not a file\n", pszFileName); return; } in = fopen(pszFileName, "r"); if (!in) { Log_Printf(LOG_DEBUG, "Keymap_LoadRemapFile: failed to " " open keymap file '%s'\n", pszFileName); return; } while (!feof(in) && idx < KBD_MAX_SCANCODE) { /* Read line from file */ if (fgets(szString, sizeof(szString), in) == NULL) break; /* Remove white-space from start of line */ Str_Trim(szString); if (strlen(szString)>0) { /* Is a comment? */ if ( (szString[0]==';') || (szString[0]=='#') ) continue; /* Read values */ sscanf(szString, "%d,%d", &PCKeyCode, &STScanCode); /* Store into remap table, check both value within range */ if (STScanCode >= 0 && STScanCode <= KBD_MAX_SCANCODE && PCKeyCode >= 8) { LoadedKeymap[idx][0] = PCKeyCode; LoadedKeymap[idx][1] = STScanCode; idx += 1; } } } fclose(in); }
/** * Command: Dump or set a DSP register */ int DebugDsp_Register(int nArgc, char *psArgs[]) { char *assign; Uint32 value; char *arg; if (!bDspEnabled) { fprintf(stderr, "DSP isn't present or initialized.\n"); return DEBUGGER_CMDDONE; } if (nArgc == 1) { /* No parameter - dump all registers */ DSP_DisasmRegisters(); return DEBUGGER_CMDDONE; } arg = psArgs[1]; assign = strchr(arg, '='); if (!assign) goto error_msg; *assign++ = '\0'; if (!Eval_Number(Str_Trim(assign), &value)) goto error_msg; if (DSP_Disasm_SetRegister(Str_Trim(arg), value)) return DEBUGGER_CMDDONE; error_msg: fprintf(stderr,"\tError, usage: dr or dr xx=yyyy\n" "\tWhere: xx=A0-A2, B0-B2, X0, X1, Y0, Y1, R0-R7,\n" "\t N0-N7, M0-M7, LA, LC, PC, SR, SP, OMR, SSH, SSL\n"); return DEBUGGER_CMDDONE; }
/** * Load keyboard remap file */ void Keymap_LoadRemapFile(char *pszFileName) { char szString[1024]; int STScanCode, PCKeyCode; FILE *in; /* Initialize table with default values */ memcpy(LoadedKeyToSTScanCode, SymbolicKeyToSTScanCode, sizeof(LoadedKeyToSTScanCode)); if (!*pszFileName) return; /* Attempt to load file */ if (!File_Exists(pszFileName)) { Log_Printf(LOG_DEBUG, "Keymap_LoadRemapFile: '%s' not a file\n", pszFileName); return; } in = fopen(pszFileName, "r"); if (!in) { Log_Printf(LOG_DEBUG, "Keymap_LoadRemapFile: failed to " " open keymap file '%s'\n", pszFileName); return; } while (!feof(in)) { /* Read line from file */ if (fgets(szString, sizeof(szString), in) == NULL) break; /* Remove white-space from start of line */ Str_Trim(szString); if (strlen(szString)>0) { /* Is a comment? */ if ( (szString[0]==';') || (szString[0]=='#') ) continue; /* Read values */ sscanf(szString, "%d,%d", &PCKeyCode, &STScanCode); /* Store into remap table, check both value within range */ if ( (PCKeyCode>=0) && (PCKeyCode<SDLK_LAST) && (STScanCode>=0) && (STScanCode<256) ) LoadedKeyToSTScanCode[PCKeyCode] = STScanCode; } } fclose(in); }
/** * Read a command line from the keyboard and return a pointer to the string. * Only string returned by this function can be given for it as argument! * @return Pointer to the string which should be given back to this * function or DebugUI_FreeCommand() for re-use/freeing. * Returns NULL when error occurred. */ static char *DebugUI_GetCommand(char *input) { fprintf(stderr, "> "); if (!input) { input = malloc(256); assert(input); } input[0] = '\0'; if (fgets(input, 256, stdin) == NULL) { free(input); return NULL; } return Str_Trim(input); }
/** * Dump or set CPU registers */ int DebugCpu_Register(int nArgc, char *psArgs[]) { char reg[3], *assign; Uint32 value; char *arg; /* If no parameter has been given, simply dump all registers */ if (nArgc == 1) { uaecptr nextpc; /* use the UAE function instead */ #ifdef WINUAE_FOR_HATARI m68k_dumpstate_file(debugOutput, &nextpc); #else m68k_dumpstate(debugOutput, &nextpc); #endif fflush(debugOutput); return DEBUGGER_CMDDONE; } arg = psArgs[1]; assign = strchr(arg, '='); if (!assign) { goto error_msg; } *assign++ = '\0'; if (!Eval_Number(Str_Trim(assign), &value)) { goto error_msg; } arg = Str_Trim(arg); if (strlen(arg) != 2) { goto error_msg; } reg[0] = toupper((unsigned char)arg[0]); reg[1] = toupper((unsigned char)arg[1]); reg[2] = '\0'; /* set SR and update conditional flags for the UAE CPU core. */ if (reg[0] == 'S' && reg[1] == 'R') { M68000_SetSR(value); } else if (reg[0] == 'P' && reg[1] == 'C') /* set PC? */ { M68000_SetPC(value); } else { Uint32 *regaddr; /* check&set data and address registers */ if (DebugCpu_GetRegisterAddress(reg, ®addr)) { *regaddr = value; } else { goto error_msg; } } return DEBUGGER_CMDDONE; error_msg: fprintf(stderr,"\tError, usage: r or r xx=yyyy\n\tWhere: xx=A0-A7, D0-D7, PC or SR.\n"); return DEBUGGER_CMDDONE; }
/** * ---------------------------------------------------------------------/ * / reads from an input configuration (INI) file. * /--------------------------------------------------------------------- * >>------[ input_config() ]-------------[ 08-02-95 14:02PM ]------/ * / return value: * / int ; number of records read or -1 on error * / parameters: * / char *filename ; filename of INI style file * / struct Config_Tag configs[]; Configuration structure * / char *header ; INI header name (i.e. "[TEST]") * /-------------------------------------------------------------------<< */ int input_config(const char *filename, const struct Config_Tag configs[], const char *header) { const struct Config_Tag *ptr; int count=0, lineno=0, type; FILE *file; char *fptr,*tok; const char *next; char line[1024]; file = fopen(filename,"r"); if (file == NULL) return -1; /* return error designation. */ if (header != NULL) { do { fptr = Str_Trim(fgets(line, sizeof(line), file)); /* get input line */ if (fptr == NULL) break; } while (memcmp(fptr,header,strlen(header))); } if ( !feof(file) ) do { fptr = Str_Trim(fgets(line, sizeof(line), file)); /* get input line */ if (fptr == NULL) continue; lineno++; if (fptr[0] == '#') continue; /* skip comments */ if (fptr[0] == '[') continue; /* skip next header */ tok = Str_Trim(strtok(fptr, "=")); /* get first token */ if (tok == NULL) continue; for (ptr = configs; ptr->buf; ++ptr) /* scan for token */ { if (!strcmp(tok, ptr->code)) /* got a match? */ { type = ptr->type; /* get actual config value */ next = Str_Trim(strtok(NULL, "=")); if (next == NULL) { if (type == String_Tag) next = ""; /* field with empty string */ else type = Error_Tag; } count++; switch (type) /* check type */ { case Bool_Tag: if (!strcasecmp(next,"FALSE")) *((bool *)(ptr->buf)) = false; else if (!strcasecmp(next,"TRUE")) *((bool *)(ptr->buf)) = true; break; case Char_Tag: sscanf(next, "%c", (char *)(ptr->buf)); break; case Short_Tag: sscanf(next, "%hd", (short *)(ptr->buf)); break; case Int_Tag: sscanf(next, "%d", (int *)(ptr->buf)); break; case Long_Tag: sscanf(next, "%ld", (long *)(ptr->buf)); break; case Float_Tag: sscanf(next, "%g", (float *)ptr->buf); break; case Double_Tag: sscanf(next, "%lg", (double *)ptr->buf); break; case String_Tag: strcpy((char *)ptr->buf, next); break; case Error_Tag: default: count--; printf("Error in Config file %s on line %d\n", filename, lineno); break; } } } } while (fptr != NULL && fptr[0] != '['); fclose(file); return count; }
/** * ---------------------------------------------------------------------/ * / updates an input configuration (INI) file from a structure. * /--------------------------------------------------------------------- * >>------[ update_config() ]-------------[ 08-02-95 14:02PM ]------/ * / return value: * / int ; Number of records read & updated * / parameters: * / char *filename ; filename of INI file * / struct Config_Tag configs[]; Configuration structure * / char *header ; INI header name (i.e. "[TEST]") * /-------------------------------------------------------------------<< */ int update_config(const char *filename, const struct Config_Tag configs[], const char *header) { const struct Config_Tag *ptr; int count=0, lineno=0, retval; FILE *cfgfile, *tempfile; char *fptr, *tok; char line[1024]; bool bUseTempCfg = false; const char *sTempCfgName = "_temp_.cfg"; cfgfile = fopen(filename, "r"); /* If the cfg file does not yet exists, we can create it directly: */ if (cfgfile == NULL) { cfgfile = fopen(filename, "w"); if (cfgfile == NULL) return -1; /* return error designation. */ count = write_header_tokens(cfgfile, configs, header); fclose(cfgfile); return count; } tempfile = tmpfile(); /* Open a temporary file for output */ if (tempfile == NULL) { /* tmpfile() failed, let's try a normal open */ tempfile = fopen(sTempCfgName, "w+"); bUseTempCfg = true; } if (tempfile == NULL) { perror("update_config"); fclose(cfgfile); return -1; /* return error designation. */ } if (header != NULL) { int headerlen = strlen(header); do { fptr = Str_Trim(fgets(line, sizeof(line), cfgfile)); /* get input line */ if (fptr == NULL) break; fprintf(tempfile, "%s\n", fptr); } while(memcmp(fptr, header, headerlen)); } if (feof(cfgfile)) { count += write_header_tokens(tempfile, configs, header); } else { char *savedtokenflags = NULL; /* Array to log the saved tokens */ int numtokens = 0; /* Total number of tokens to save */ /* Find total number of tokens: */ for (ptr=configs; ptr->buf; ++ptr) { numtokens += 1; } if (numtokens) { savedtokenflags = malloc(numtokens * sizeof(char)); if (savedtokenflags) memset(savedtokenflags, 0, numtokens * sizeof(char)); } for(;;) { fptr = Str_Trim(fgets(line, sizeof(line), cfgfile)); /* get input line */ /* error or eof? */ if (fptr == NULL) break; lineno++; if (fptr[0] == '#') { fprintf(tempfile, "%s\n", fptr); continue; /* skip comments */ } if (fptr[0] == '[') { break; } tok = Str_Trim(strtok(fptr, "=")); /* get first token */ if (tok != NULL) { int i = 0; for (ptr = configs; ptr->buf; ++ptr, i++) /* scan for token */ { if (!strcmp(tok, ptr->code)) /* got a match? */ { if (write_token(tempfile, ptr) == 0) { if (savedtokenflags) savedtokenflags[i] = true; count += 1; } } } } } /* Write remaining (new?) tokens that were not in the configuration file, yet */ if (count != numtokens && savedtokenflags != NULL) { int i; for (ptr = configs, i = 0; ptr->buf; ++ptr, i++) { if (!savedtokenflags[i]) { if (write_token(tempfile, ptr) == 0) { count += 1; fprintf(stderr, "Wrote new token %s -> %s \n", header, ptr->code); } } } } if (savedtokenflags) { free(savedtokenflags); savedtokenflags = NULL; } if (!feof(cfgfile) && fptr != NULL) fprintf(tempfile, "\n%s\n", line); for(;;) { fptr = Str_Trim(fgets(line, sizeof(line), cfgfile)); /* get input line */ if (fptr == NULL) break; fprintf(tempfile, "%s\n", fptr); } } /* Re-open the config file for writing: */ fclose(cfgfile); cfgfile = fopen(filename, "wb"); if (cfgfile == NULL || fseek(tempfile, 0, SEEK_SET) != 0) { retval = -1; goto cleanup; } /* Now copy the temporary file to the configuration file: */ retval = count; while(!(feof(tempfile) || ferror(cfgfile))) { size_t copycount; copycount = fread(line, sizeof(char), sizeof(line), tempfile); if (copycount == 0) break; if (fwrite(line, sizeof(char), copycount, cfgfile) != copycount) { retval = -1; break; } } cleanup: if (cfgfile) { if (ferror(cfgfile)) perror("update_config"); fclose(cfgfile); } if (tempfile) { /* tmpfile() is removed automatically on close */ fclose(tempfile); if (bUseTempCfg) unlink(sTempCfgName); } return retval; }
/** * Read debugger commands from a file. If 'reinit' is set * (as it normally should), reinitialize breakpoints etc. * afterwards. return false for error, true for success. */ bool DebugUI_ParseFile(const char *path, bool reinit) { char *olddir, *dir, *cmd, *input, *expanded, *slash; FILE *fp; fprintf(stderr, "Reading debugger commands from '%s'...\n", path); if (!(fp = fopen(path, "r"))) { perror("ERROR"); return false; } /* change to directory where the debugger file resides */ olddir = NULL; dir = strdup(path); slash = strrchr(dir, PATHSEP); if (slash) { olddir = malloc(FILENAME_MAX); if (olddir) { if (!getcwd(olddir, FILENAME_MAX)) strcpy(olddir, "."); } *slash = '\0'; if (chdir(dir) != 0) { perror("ERROR"); if (olddir) free(olddir); free(dir); fclose(fp); return false; } fprintf(stderr, "Changed to input file dir '%s'.\n", dir); } free(dir); input = NULL; for (;;) { if (!input) { input = malloc(256); assert(input); } if (!fgets(input, 256, fp)) break; /* ignore empty and comment lines */ cmd = Str_Trim(input); if (!*cmd || *cmd == '#') continue; /* returns new string if input needed expanding! */ expanded = DebugUI_EvaluateExpressions(input); if (!expanded) continue; cmd = Str_Trim(expanded); fprintf(stderr, "> %s\n", cmd); DebugUI_ParseCommand(cmd); free(expanded); } free(input); fclose(fp); if (olddir) { if (chdir(olddir) != 0) perror("ERROR"); else fprintf(stderr, "Changed back to '%s' dir.\n", olddir); free(olddir); } if (reinit) { DebugCpu_SetDebugging(); DebugDsp_SetDebugging(); } return true; }