Recipe cooking is working!

This commit is contained in:
Scott Duensing 2023-04-23 19:18:53 -05:00
parent f513dc3893
commit 4b32b111cf
19 changed files with 677 additions and 157 deletions

View file

@ -37,23 +37,25 @@ option(DEBUG_MODE "Enable debugging output and memory tracing?" ON)
set(CMAKE_C_STANDARD 99)
set(SOURCE_FILES
thirdparty-installed/memwatch/memwatch.c
thirdparty-installed/cwalk-master/src/cwalk.c
ui/generated/resources.c
src/main.c
src/utils.c
src/joeydev.c
src/vector.c
src/array.c
src/draw.c
src/image.c
src/vecparse.c
src/color.c
src/palette.c
src/project.c
src/ssh.c
src/http.c
src/editor.c
thirdparty-installed/memwatch/memwatch.c
thirdparty-installed/cwalk-master/src/cwalk.c
ui/generated/resources.c
src/main.c
src/utils.c
src/joeydev.c
src/vector.c
src/array.c
src/draw.c
src/image.c
src/vecparse.c
src/color.c
src/palette.c
src/project.c
src/ssh.c
src/http.c
src/editor.c
src/compiler.c
src/messages.c
)
configure_file(include/config.h.in config.h)
@ -72,6 +74,8 @@ add_custom_target(GENERATE_UI_HEADERS
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libgcrypt.a
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libssh2.a
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libz.a
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libtcc.a
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/tcc/libtcc1.a
)
add_dependencies(${CMAKE_PROJECT_NAME} GENERATE_UI_HEADERS)
@ -116,6 +120,8 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libgpg-error.a
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libcurl.a
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libz.a
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libtcc.a
${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/tcc/libtcc1.a
${GTK3_LIBRARIES}
-ldl
-pthread

36
embedded/recipe.h Normal file
View file

@ -0,0 +1,36 @@
/*
* JoeyDev
* Copyright (C) 2018-2023 Scott Duensing <scott@kangaroopunch.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef RECIPE_H
#define RECIPE_H
#include <tcclib.h>
extern char **___recipeTargets;
extern void recipeAddTarget(char *target);
extern void recipeMessage(char *format, ...);
#endif // RECIPE_H

View file

@ -56,4 +56,7 @@ typedef struct WindowDataS {
} WindowDataT;
extern char *__resourcePath;
#endif // COMMON_H

30
include/compiler.h Normal file
View file

@ -0,0 +1,30 @@
/*
* JoeyDev
* Copyright (C) 2018-2023 Scott Duensing <scott@kangaroopunch.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef COMPILER_H
#define COMPILER_H
int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context);
#endif // COMPILER_H

40
include/messages.h Normal file
View file

@ -0,0 +1,40 @@
/*
* JoeyDev
* Copyright (C) 2018-2023 Scott Duensing <scott@kangaroopunch.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef MESSAGES_H
#define MESSAGES_H
enum MessageTypesE {
MSG_INFO = 0,
MSG_WARN,
MSG_ERROR,
MSG_SEVERE, // This means something failed in JoeyDev itself.
MSG_COUNT
};
typedef enum MessageTypesE MessageTypesT;
void message(MessageTypesT level, char *format, ...);
#endif //MESSAGES_H

View file

@ -24,7 +24,11 @@
#define PROJECT_H
void winProjectCreate(void);
struct ProjectDataS;
gboolean projectAddToTree(struct ProjectDataS *self, char *filename);
void winProjectCreate(void);
#endif // PROJECT_H

View file

@ -42,6 +42,7 @@ char *utilCreateStringVArgs(char *format, va_list args);
char *utilDeobfuscateASCII(char *obfuscated);
void utilDequote(char *string);
void utilEnsureBufferSize(unsigned char **buffer, int *length, int wanted);
void utilExtractResource(char *path);
char *utilFileBasename(char *path);
gboolean utilFileExists(char *filename);
gboolean utilFileOpen(WindowDataT *self, char *extension, char *what);

125
src/compiler.c Normal file
View file

@ -0,0 +1,125 @@
/*
* JoeyDev
* Copyright (C) 2018-2023 Scott Duensing <scott@kangaroopunch.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "common.h"
#include "compiler.h"
#include "libtcc.h"
#include "project.h"
#include "messages.h"
#include "utils.h"
#include "array.h"
char **___recipeTargets = NULL;
static void compilerErrorHandler(void *opaque, const char *msg);
void recipeAddTarget(char *target);
void recipeMessage(char *format, ...);
static void compilerErrorHandler(void *opaque, const char *msg) {
char *isWarning = strstr(msg, " warning: ");
(void)opaque;
message(isWarning == NULL ? MSG_ERROR : MSG_WARN, "%s", msg);
}
// All the paths passed in here are expected to be complete and absolute.
int compilerRunRecipe(char *recipe, char *input, char *outputPath, void *context) {
TCCState *s;
int result;
int (*entry)(char *, char *);
___recipeTargets = NULL;
s = tcc_new();
if (!s) {
// Something bad happened.
return -1;
}
tcc_set_options(s, "-Wall -Wno-write-strings");
tcc_set_lib_path(s, __resourcePath);
tcc_add_sysinclude_path(s, __resourcePath);
tcc_set_error_func(s, stdout, compilerErrorHandler);
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
if (tcc_add_file(s, recipe) < 0) {
// Errors in code.
tcc_delete(s);
return -4;
}
tcc_add_symbol(s, "___recipeTargets", ___recipeTargets);
tcc_add_symbol(s, "recipeAddTarget", recipeAddTarget);
tcc_add_symbol(s, "recipeMessage", recipeMessage);
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) {
// Something bad happened.
tcc_delete(s);
return -2;
}
entry = tcc_get_symbol(s, "recipe");
if (!entry) {
// Something bad happened.
tcc_delete(s);
return -3;
}
result = entry(input, outputPath);
while (arrlen(___recipeTargets) > 0) {
if (projectAddToTree(context, ___recipeTargets[0])) {
utilSetDirty((WindowDataT *)context, TRUE);
}
DEL(___recipeTargets[0]);
arrdel(___recipeTargets, 0);
}
ARRFREE(___recipeTargets);
tcc_delete(s);
return result;
}
void recipeAddTarget(char *target) {
arrput(___recipeTargets, strdup(target));
}
void recipeMessage(char *format, ...) {
va_list args;
char *string;
va_start(args, format);
string = utilCreateStringVArgs(format, args);
va_end(args);
message(MSG_INFO, "%s", string);
DEL(string);
}

View file

@ -26,6 +26,10 @@
#include "joeydev.h"
#include "http.h"
#include "ssh.h"
#include "utils.h"
char *__resourcePath = NULL;
int main(int argc, char **argv) {
@ -35,9 +39,30 @@ int main(int argc, char **argv) {
#endif
gtk_init(&argc, &argv);
// Make sure we have a config & resources folder.
__resourcePath = utilCreateString("%s%cjoeydev%cresources%c", g_get_user_config_dir(), UTIL_PATH_CHAR, UTIL_PATH_CHAR, UTIL_PATH_CHAR);
utilMkDirP(__resourcePath, 0777);
httpStartup();
sshStartup();
// Extract files we need later.
utilExtractResource("/com/kangaroopunch/joeydev/resources/libtcc.a");
utilExtractResource("/com/kangaroopunch/joeydev/resources/libtcc1.a");
utilExtractResource("/com/kangaroopunch/joeydev/resources/float.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/stdalign.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/stdarg.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/stdatomic.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/stdbool.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/stddef.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/stdnoreturn.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/tccdefs.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/tcclib.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/tgmath.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/varargs.h");
utilExtractResource("/com/kangaroopunch/joeydev/resources/recipe.h");
winJoeyDevCreate();
gtk_main();
@ -45,5 +70,7 @@ int main(int argc, char **argv) {
sshShutdown();
httpShutdown();
DEL(__resourcePath);
return 0;
}

113
src/messages.c Normal file
View file

@ -0,0 +1,113 @@
/*
* JoeyDev
* Copyright (C) 2018-2023 Scott Duensing <scott@kangaroopunch.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "common.h"
#include "messages.h"
#include "utils.h"
static GtkWidget *_lstMessages = NULL;
EVENT gboolean winMessagesClose(GtkWidget *object, gpointer userData);
static void winMessagesDelete(gpointer userData);
void message(MessageTypesT level, char *format, ...) {
WindowDataT *self = NULL;
char *widgetNames[] = {
"winMessages",
"lstMessages",
NULL
};
GtkWidget **widgets[] = {
NULL,
&_lstMessages
};
GtkWidget *row;
GtkWidget *box;
GtkWidget *label;
va_list args;
char *string;
char *temp;
char *labels[MSG_COUNT] = {
"<span foreground=\"gray\"> Info:</span>",
"<span foreground=\"yellow\">Warning:</span>",
"<span foreground=\"red\"> Error:</span>",
"<span foreground=\"red\"><b> Severe:</b></span>"
};
// Do we need to open this window?
if (!_lstMessages) {
// Set up instance data. We only need WindowDataT since this is a "singleton" window.
self = NEW(WindowDataT);
self->closeWindow = winMessagesClose;
widgets[0] = &self->window;
utilGetWidgetsFromMemory("/com/kangaroopunch/joeydev/Messages.glade", widgetNames, widgets, self);
// Register window.
utilWindowRegister(self);
// Show window.
gtk_widget_show_all(self->window);
}
// Display message.
va_start(args, format);
temp = utilCreateStringVArgs(format, args);
va_end(args);
string = utilCreateString("<tt>%s %s</tt>", labels[level], temp);
row = gtk_list_box_row_new();
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,6);
gtk_widget_set_hexpand(box, TRUE);
label = gtk_label_new(string);
gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
DEL(string);
gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
gtk_container_add(GTK_CONTAINER(row), box);
gtk_list_box_insert(GTK_LIST_BOX(_lstMessages), row, -1);
gtk_widget_show_all(row);
}
EVENT gboolean winMessagesClose(GtkWidget *object, gpointer userData) {
// userData is not reliable due to util indirectly calling us.
WindowDataT *self = (WindowDataT *)utilGetWindowData(object);
(void)userData;
winMessagesDelete(self);
return FALSE;
}
static void winMessagesDelete(gpointer userData) {
utilWindowUnRegister(userData);
_lstMessages = NULL;
DEL(userData);
}

View file

@ -31,6 +31,8 @@
#include "utils.h"
#include "http.h"
#include "ssh.h"
#include "messages.h"
#include "compiler.h"
enum ProjectColumnsE {
@ -88,24 +90,25 @@ typedef struct SectionDataS {
// These have to match ProjectSectionTypeT above.
static SectionDataT _sectionData[] = {
{ "Header", "*.h" },
{ "Code", "*.c" },
{ "Bitmap", "*.img" },
{ "Stencil", "*.stn" },
{ "Vector", "*.vic" },
{ "Sound", "*.snd" },
{ "Music", "*.mod" },
{ "Header", "*.h" },
{ "Code", "*.c" },
{ "Bitmap", "*.img" },
{ "Stencil", "*.stn" },
{ "Vector", "*.vic" },
{ "Sound", "*.snd" },
{ "Music", "*.mod" },
{ "Raw Data", NULL },
{ "Cooked Data", "*.dat" },
{ NULL, NULL }
};
static ProjectDataT *_cookingProjectData = NULL;
#define BUILD_SETTINGS_RESPONSE_TEST 1
static void addToRecipeData(ProjectDataT *self, char *key, char *value);
static void addToTree(ProjectDataT *self, char *filename);
EVENT void buildTargetClicked(GtkButton *widget, gpointer userData);
EVENT void btnEditRecipeClicked(GtkButton *widget, gpointer userData);
EVENT void btnNewRecipeClicked(GtkButton *widget, gpointer userData);
@ -123,6 +126,7 @@ EVENT void menuProjectProjectAdd(GtkWidget *object, gpointer userData);
EVENT void menuProjectProjectRemove(GtkWidget *object, gpointer userData);
EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData);
EVENT void menuProjectBuildTargets(GtkWidget *object, gpointer userData);
EVENT void menuProjectBuildCookRecipes(GtkWidget *object, gpointer userData);
EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData);
EVENT void menuProjectHelpProject(GtkWidget *object, gpointer userData);
static void saveConfig(ProjectDataT *self);
@ -148,59 +152,6 @@ static void addToRecipeData(ProjectDataT *self, char *key, char *value) {
}
static void addToTree(ProjectDataT *self, char *filename) {
ProjectSectionTypeT section;
char *temp = NULL;
GtkTreeIter iter;
GtkTreeIter child;
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->treeProject));
ProjectSectionTypeT foundAt = SECTION_RAW_DATA; // If it isn't a file we know, put it in "Raw Data".
int fileLen;
int extLen;
// Is it long enough?
if (strlen(filename) > 2) {
// Is this already in the tree? This is a pretty brain-dead test.
gtk_tree_model_get_iter_first(model, &iter);
do {
if (gtk_tree_model_iter_children(model, &child, &iter)) {
do {
gtk_tree_model_get(model, &child, COL_FILENAME, &temp, -1);
if (strcmp(temp, filename) == 0) {
DEL(temp); // This generates an unknown pointer warning in memwatch. Pretty sure it's bogus.
return; // Silently fail to add on name collision.
}
DEL(temp); // This generates an unknown pointer warning in memwatch. Pretty sure it's bogus.
} while (gtk_tree_model_iter_next(model, &child));
}
} while (gtk_tree_model_iter_next(model, &iter));
// Find proper section.
for (section = 0; section < SECTION_COUNT; section++) {
if (_sectionData[section].extension != NULL) {
// Compare last two bytes of filename with extension - it's enough to differentiate them and allows for ".c" and ".h".
fileLen = strlen(filename) - 1;
extLen = strlen(_sectionData[section].extension) - 1;
if (filename[fileLen - 1] == _sectionData[section].extension[extLen - 1] && filename[fileLen] == _sectionData[section].extension[extLen]) {
foundAt = section;
break;
}
}
}
DEL(temp);
fileLen = 0;
utilEnsureBufferSize((unsigned char **)&temp, &fileLen, 4); // fileLen is just a throwaway here.
snprintf(temp, 4, "%d", foundAt);
gtk_tree_model_get_iter_from_string(model, &iter, temp);
gtk_tree_store_append(GTK_TREE_STORE(model), &child, &iter);
gtk_tree_store_set(GTK_TREE_STORE(model), &child, COL_FILENAME, filename, -1);
DEL(temp);
gtk_tree_view_expand_all(GTK_TREE_VIEW(self->treeProject));
}
}
EVENT void buildTargetClicked(GtkButton *widget, gpointer userData) {
ArchT *arch = (ArchT *)userData;
@ -232,14 +183,18 @@ EVENT void btnNewRecipeClicked(GtkButton *widget, gpointer userData) {
if (utilFileSaveOtherAs((WindowDataT *)userData, "*.c", "Recipe", &newFile)) {
out = fopen(newFile, "wt");
fprintf(out, ""
"//\n"
"// JoeyBuild Recipe Program\n"
"//\n"
"\n"
"int recipe(char *fileIn, char *fileOut) {\n"
"\n"
"\treturn 0; // Return a non-zero value on failure.\n"
"}\n"
"//\n"
"// JoeyBuild Recipe Program\n"
"//\n"
"\n"
"\n"
"#include <recipe.h>\n"
"\n"
"\n"
"int recipe(char *fileIn, char *outputPath) {\n"
"\n"
"\treturn 0; // Return a positive non-zero value on failure.\n"
"}\n"
);
fclose(out);
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(self->tempWidget), newFile);
@ -263,14 +218,12 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) {
GtkWidget *lblRaw;
GtkWidget *fileRecipe;
GtkWidget *btnNewRecipe;
GtkWidget *lblCooked;
GtkWidget *btnCancel;
GtkWidget *btnOkay;
int original;
int result;
int i;
char *raw = NULL;
char *cooked = NULL;
char *temp = NULL;
char *path = NULL;
char *widgetNames[] = {
@ -278,7 +231,6 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) {
"lblRaw",
"fileRecipe",
"btnNewRecipe",
"lblCooked",
"btnCancel",
"btnOkay",
NULL
@ -288,7 +240,6 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) {
&lblRaw,
&fileRecipe,
&btnNewRecipe,
&lblCooked,
&btnCancel,
&btnOkay
};
@ -297,9 +248,6 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) {
raw = utilFileBasename(filename);
gtk_label_set_text(GTK_LABEL(lblRaw), raw);
cooked = utilFileRemoveExtension(raw);
strcat(cooked, ".dat");
gtk_label_set_text(GTK_LABEL(lblCooked), cooked);
self->tempWidget = fileRecipe;
@ -326,7 +274,6 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) {
}
// Did the recipe change?
if (!((original >= 0) && (strcmp(self->recipes[original]->value, temp) == 0))) {
addToTree(self, cooked);
addToRecipeData(self, raw, temp);
utilSetDirty((WindowDataT *)self, TRUE);
}
@ -335,7 +282,6 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) {
}
DEL(path);
DEL(cooked);
DEL(raw);
self->tempWidget = NULL;
@ -436,7 +382,6 @@ static void loadProject(ProjectDataT *self) {
int j;
char *path = NULL;
char *raw = NULL;
char *cooked = NULL;
in = fopen(self->windowData.filename, "rt");
if (in != NULL) {
@ -463,9 +408,9 @@ static void loadProject(ProjectDataT *self) {
utilDequote(c);
cwk_path_get_relative(path, c, __utilFilenameBuffer, sizeof(__utilFilenameBuffer));
if (__utilFilenameBuffer[0] == 0) {
addToTree(self, c);
projectAddToTree(self, c);
} else {
addToTree(self, __utilFilenameBuffer);
projectAddToTree(self, __utilFilenameBuffer);
}
continue;
}
@ -502,20 +447,14 @@ static void loadProject(ProjectDataT *self) {
c = utilGetToken(NULL, " ", "\"", "\"");
utilDequote(c);
raw = strdup(c);
cooked = utilFileRemoveExtension(raw);
strcat(cooked, ".dat");
addToTree(self, cooked);
c = utilGetToken(NULL, " ", "\"", "\"");
utilDequote(c);
cwk_path_get_relative(path, c, __utilFilenameBuffer, sizeof(__utilFilenameBuffer));
if (__utilFilenameBuffer[0] == 0) {
addToRecipeData(self, raw, c);
debug("Writing Recipe [%s] = [%s]\n", raw, c);
} else {
addToRecipeData(self, raw, __utilFilenameBuffer);
debug("Writing Recipe [%s] = [%s]\n", raw, __utilFilenameBuffer);
}
DEL(cooked);
DEL(raw);
}
@ -715,7 +654,7 @@ EVENT void menuProjectProjectAdd(GtkWidget *object, gpointer userData) {
DEL(temp);
temp = strdup(__utilFilenameBuffer);
}
addToTree(self, temp);
projectAddToTree(self, temp);
utilSetDirty((WindowDataT *)self, TRUE);
DEL(temp);
}
@ -731,6 +670,8 @@ EVENT void menuProjectProjectRemove(GtkWidget *object, gpointer userData) {
GtkWidget *dialog;
GtkTreeModel *model;
GtkTreeIter iter;
char *name = NULL;
int i;
(void)object;
@ -743,6 +684,12 @@ EVENT void menuProjectProjectRemove(GtkWidget *object, gpointer userData) {
}
if (found) {
// Delete cook recipe if it exists.
gtk_tree_model_get(model, &iter, COL_FILENAME, &name, -1);
i = findRecipeData(self, name);
if (i >= 0) arrdel(self->recipes, i);
DEL(name);
// Remove item from tree.
gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
utilSetDirty((WindowDataT *)self, TRUE);
} else {
@ -947,8 +894,51 @@ EVENT void menuProjectBuildTargets(GtkWidget *object, gpointer userData) {
}
EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
EVENT void menuProjectBuildCookRecipes(GtkWidget *object, gpointer userData) {
ProjectDataT *self = (ProjectDataT *)userData;
int i;
char *raw;
char *recipe;
char *path;
int result;
// Only one cook at a time. Should not be able to happen.
if (_cookingProjectData) {
message(MSG_ERROR, "Cook currently running");
return;
}
// Remember who started the cook.
_cookingProjectData = self;
// Find path of project file.
path = strdup(self->windowData.filename);
cwk_path_get_dirname(path, (size_t *)&i);
if (i > 0) path[i] = 0;
for (i=0; i<arrlen(self->recipes); i++) {
// Build pathnames.
cwk_path_change_basename(self->windowData.filename, self->recipes[i]->key, __utilFilenameBuffer, sizeof(__utilFilenameBuffer));
raw = strdup(__utilFilenameBuffer);
cwk_path_change_basename(self->windowData.filename, self->recipes[i]->value, __utilFilenameBuffer, sizeof(__utilFilenameBuffer));
recipe = strdup(__utilFilenameBuffer);
// Run it!
message(MSG_INFO, "Cooking %s", self->recipes[i]->key);
result = compilerRunRecipe(recipe, raw, path, self);
if (result != 0) {
//***TODO*** Not all negative returns are severe.
message(result > 0 ? MSG_ERROR : MSG_SEVERE, "Recipe %s returned %d", self->recipes[i]->value, result);
}
message(MSG_INFO, "Finished Cooking");
}
DEL(path);
_cookingProjectData = NULL;
}
EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
}
@ -960,15 +950,65 @@ EVENT void menuProjectHelpProject(GtkWidget *object, gpointer userData) {
}
gboolean projectAddToTree(ProjectDataT *self, char *filename) {
ProjectSectionTypeT section;
char *temp = NULL;
GtkTreeIter iter;
GtkTreeIter child;
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->treeProject));
ProjectSectionTypeT foundAt = SECTION_RAW_DATA; // If it isn't a file we know, put it in "Raw Data".
int fileLen;
int extLen;
// Is it long enough?
if (strlen(filename) > 2) {
// Is this already in the tree? This is a pretty brain-dead test.
gtk_tree_model_get_iter_first(model, &iter);
do {
if (gtk_tree_model_iter_children(model, &child, &iter)) {
do {
gtk_tree_model_get(model, &child, COL_FILENAME, &temp, -1);
if (strcmp(temp, filename) == 0) {
DEL(temp); // This generates an unknown pointer warning in memwatch. Pretty sure it's bogus.
return FALSE; // Item exists and was not added.
}
DEL(temp); // This generates an unknown pointer warning in memwatch. Pretty sure it's bogus.
} while (gtk_tree_model_iter_next(model, &child));
}
} while (gtk_tree_model_iter_next(model, &iter));
// Find proper section.
for (section = 0; section < SECTION_COUNT; section++) {
if (_sectionData[section].extension != NULL) {
// Compare last two bytes of filename with extension - it's enough to differentiate them and allows for ".c" and ".h".
fileLen = strlen(filename) - 1;
extLen = strlen(_sectionData[section].extension) - 1;
if (filename[fileLen - 1] == _sectionData[section].extension[extLen - 1] && filename[fileLen] == _sectionData[section].extension[extLen]) {
foundAt = section;
break;
}
}
}
DEL(temp);
fileLen = 0;
utilEnsureBufferSize((unsigned char **)&temp, &fileLen, 4); // fileLen is just a throwaway here.
snprintf(temp, 4, "%d", foundAt);
gtk_tree_model_get_iter_from_string(model, &iter, temp);
gtk_tree_store_append(GTK_TREE_STORE(model), &child, &iter);
gtk_tree_store_set(GTK_TREE_STORE(model), &child, COL_FILENAME, filename, -1);
DEL(temp);
gtk_tree_view_expand_all(GTK_TREE_VIEW(self->treeProject));
}
return TRUE; // Item was added.
}
static void saveConfig(ProjectDataT *self) {
char *temp;
FILE *out;
// Make sure we have a config folder.
temp = utilCreateString("%s%cjoeydev", g_get_user_config_dir(), UTIL_PATH_CHAR);
utilMkDirP(temp, 0777);
DEL(temp);
// Save config.
out = fopen(self->configName, "wt");
if (out != NULL) {
@ -1058,7 +1098,7 @@ static gboolean updateBuildOptions(ProjectDataT *self) {
if (utilFileExists(name) == TRUE) {
in = fopen(name, "rt");
if (in != NULL) {
utilEnsureBufferSize(&line, &len, 1024); // Not technically needed, but fixes a pointer warning from memmaker.
utilEnsureBufferSize((unsigned char **)&line, (int *)&len, 1024); // Not technically needed, but fixes a pointer warning from memmaker.
while (getline(&line, &len, in) != -1) {
if (strlen(line) > 0) line[strlen(line) - 1] = 0;
c = utilGetToken(line, " ", "\"", "\"");
@ -1236,9 +1276,6 @@ void winProjectCreate(void) {
//***DEBUG***
self->windowData.filename = strdup("/home/scott/joeyapps/warehouse/Warehouse.joe");
loadProject(self);
for (int i=0; i<arrlen(self->recipes); i++) {
debug("Reading Recipe %d [%s] = [%s]\n", i, self->recipes[i]->key, self->recipes[i]->value);
}
}

View file

@ -22,6 +22,7 @@
#include <sys/stat.h>
#include "common.h"
#include "utils.h"
#include "cwalk.h"
@ -130,6 +131,46 @@ void utilEnsureBufferSize(unsigned char **buffer, int *length, int wanted) {
}
void utilExtractResource(char *path) {
GInputStream *in;
gssize read;
gssize bytes = 0;
FILE *out = NULL;
unsigned char *buffer = NULL;
int name = (int)strlen(path) - 1;
char *target = NULL;
while (name >= 0 && path[name] != '/') name--;
target = utilCreateString("%s%s", __resourcePath, &path[name + 1]);
if (!utilFileExists(target)) {
utilEnsureBufferSize(&buffer, (int *)&bytes, 8192);
in = g_resources_open_stream(path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
if (in) {
out = fopen(target, "wb");
if (out) {
do {
read = g_input_stream_read(in, buffer, bytes, NULL, NULL);
fwrite(buffer, read, 1, out);
} while (read > 0);
fclose(out);
} else {
debug("Unable to write resource %s!\n", target);
}
g_input_stream_close(in, NULL, NULL);
g_object_unref(in);
} else {
debug("Resource %s not found!\n", path);
}
DEL(buffer);
}
DEL(target);
}
char *utilFileBasename(char *path) {
const char *basename;
size_t length;
@ -231,6 +272,8 @@ gboolean utilFileSaveAs(WindowDataT *self, char *extension, char *what) {
char *files = utilCreateString("%s Files", what);
int x;
//***TODO*** Make this use utilFileSaveOtherAS
dialog = gtk_file_chooser_dialog_new("Save As",
GTK_WINDOW(self->window),
GTK_FILE_CHOOSER_ACTION_SAVE,
@ -240,7 +283,7 @@ gboolean utilFileSaveAs(WindowDataT *self, char *extension, char *what) {
if (self->filename != NULL) {
memcpy(__utilFilenameBuffer, self->filename, strlen(self->filename) + 1);
cwk_path_get_dirname(__utilFilenameBuffer, &x);
cwk_path_get_dirname(__utilFilenameBuffer, (size_t *)&x);
if (x > 0) __utilFilenameBuffer[x] = 0;
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),__utilFilenameBuffer);
}
@ -283,7 +326,7 @@ gboolean utilFileSaveOtherAs(WindowDataT *self, char *extension, char *what, cha
if (*filename != NULL) {
memcpy(__utilFilenameBuffer, *filename, strlen(*filename) + 1);
cwk_path_get_dirname(__utilFilenameBuffer, &x);
cwk_path_get_dirname(__utilFilenameBuffer, (size_t *)&x);
if (x > 0) __utilFilenameBuffer[x] = 0;
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),__utilFilenameBuffer);
}
@ -519,7 +562,7 @@ void utilWindowRegister(gpointer windowData) {
w->title = strdup(gtk_window_get_title(GTK_WINDOW(w->window)));
hmput(_windowList, w->window, windowData);
debug("Window Registered: %d\n", hmlen(_windowList));
debug("Window Registered: %ld\n", hmlen(_windowList));
}

View file

@ -611,7 +611,7 @@ static void loadVectorImage(VectorDataT *self) {
in = fopen(self->windowData.filename, "rt");
if (in != NULL) {
self->buffer[0] = 0;
utilEnsureBufferSize(&line, &len, 1024); // Not technically needed, but fixes a pointer warning from memmaker.
utilEnsureBufferSize((unsigned char **)&line, (int *)&len, 1024); // Not technically needed, but fixes a pointer warning from memmaker.
while (getline(&line, &len, in) != -1) {
switch (count) {
case 0: // Version Number

BIN
thirdparty/tinycc-0.9.27.tar.bz2 (Stored with Git LFS) vendored Normal file

Binary file not shown.

View file

@ -152,6 +152,19 @@ pushd "${ROOT}" || exit &> /dev/null
popd || true &> /dev/null
fi
if [[ ! -f ${INSTALLED}/lib/libtcc.a ]]; then
echo Building Dependency: TinyCC...
tar xzf ${THIRDPARTY}/tinycc-0.9.27.tar.bz2
pushd tinycc-0.9.27 || exit &> /dev/null
./configure \
--prefix=${INSTALLED} \
--enable-static \
--with-libgcc
make
make install
popd || true &> /dev/null
fi
popd || true &> /dev/null
echo Generating UI Embedded Code...

View file

@ -2,6 +2,11 @@
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkFileFilter" id="filefilterRecipe">
<patterns>
<pattern>*.c</pattern>
</patterns>
</object>
<object class="GtkDialog" id="dialogCookSettings">
<property name="can-focus">False</property>
<property name="title" translatable="yes">Cook Data</property>
@ -56,7 +61,7 @@
<property name="valign">center</property>
<property name="orientation">vertical</property>
<child>
<!-- n-columns=4 n-rows=3 -->
<!-- n-columns=4 n-rows=2 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
@ -127,31 +132,6 @@
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Cooked:</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lblCooked">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">lblCooked</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnEdit">
<property name="label" translatable="yes">Edit</property>
@ -187,9 +167,4 @@
<action-widget response="-5">btnOkay</action-widget>
</action-widgets>
</object>
<object class="GtkFileFilter" id="filefilterRecipe">
<patterns>
<pattern>*.c</pattern>
</patterns>
</object>
</interface>

31
ui/Messages.glade Normal file
View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow" id="winMessages">
<property name="can-focus">False</property>
<property name="title" translatable="yes">Messages</property>
<property name="default-width">440</property>
<property name="default-height">250</property>
<signal name="delete-event" handler="winMessagesClose" swapped="no"/>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkListBox" id="lstMessages">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

View file

@ -155,6 +155,22 @@
<property name="can-focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuProjectBuildCookRecipes">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Cook Recipes</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuProjectBuildCookRecipes" swapped="no"/>
<accelerator key="r" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuProjectBuildBuild">
<property name="visible">True</property>

View file

@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/com/kangaroopunch/joeydev">
<file preprocess="xml-stripblanks">JoeyDev.glade</file>
<file preprocess="xml-stripblanks">Project.glade</file>
<file preprocess="xml-stripblanks">BuildServer.glade</file>
<file preprocess="xml-stripblanks">Cook.glade</file>
<file preprocess="xml-stripblanks">Editor.glade</file>
<file preprocess="xml-stripblanks">Vector.glade</file>
<file compressed="true" preprocess="xml-stripblanks">JoeyDev.glade</file>
<file compressed="true" preprocess="xml-stripblanks">Project.glade</file>
<file compressed="true" preprocess="xml-stripblanks">BuildServer.glade</file>
<file compressed="true" preprocess="xml-stripblanks">Cook.glade</file>
<file compressed="true" preprocess="xml-stripblanks">Editor.glade</file>
<file compressed="true" preprocess="xml-stripblanks">Vector.glade</file>
<file compressed="true" preprocess="xml-stripblanks">Messages.glade</file>
<file>Logo.png</file>
</gresource>
<gresource prefix="/com/kangaroopunch/joeydev/icons/32x32/actions">
@ -20,4 +21,20 @@
<file>action-color.png</file>
<file>action-palette.png</file>
</gresource>
<gresource prefix="/com/kangaroopunch/joeydev/resources">
<file compressed="true" alias="libtcc.a">../thirdparty-installed/lib/libtcc.a</file>
<file compressed="true" alias="libtcc1.a">../thirdparty-installed/lib/tcc/libtcc1.a</file>
<file compressed="true" alias="float.h">../thirdparty-installed/lib/tcc/include/float.h</file>
<file compressed="true" alias="stdalign.h">../thirdparty-installed/lib/tcc/include/stdalign.h</file>
<file compressed="true" alias="stdarg.h">../thirdparty-installed/lib/tcc/include/stdarg.h</file>
<file compressed="true" alias="stdatomic.h">../thirdparty-installed/lib/tcc/include/stdatomic.h</file>
<file compressed="true" alias="stdbool.h">../thirdparty-installed/lib/tcc/include/stdbool.h</file>
<file compressed="true" alias="stddef.h">../thirdparty-installed/lib/tcc/include/stddef.h</file>
<file compressed="true" alias="stdnoreturn.h">../thirdparty-installed/lib/tcc/include/stdnoreturn.h</file>
<file compressed="true" alias="tccdefs.h">../thirdparty-installed/lib/tcc/include/tccdefs.h</file>
<file compressed="true" alias="tcclib.h">../thirdparty-installed/lib/tcc/include/tcclib.h</file>
<file compressed="true" alias="tgmath.h">../thirdparty-installed/lib/tcc/include/tgmath.h</file>
<file compressed="true" alias="varargs.h">../thirdparty-installed/lib/tcc/include/varargs.h</file>
<file compressed="true" alias="recipe.h">../embedded/recipe.h</file>
</gresource>
</gresources>