Add install target
[tmk.git] / tm_core_cmds.c
blob12707f6f17a2fa6b2b8a74e631a38b95f15da75e
1 #include <stdio.h>
2 #include <string.h>
3 #include <unistd.h> /* TODO: I doubt this works on Windows... */
5 #define JIM_EMBEDDED
6 #include <jim.h>
8 #include "tm_target.h"
9 #include "tm_core_cmds.h"
10 #include "tm_crypto.h"
12 static int ruleCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
14 tm_rule *rule = NULL;
15 target_list *deps = NULL;
16 Jim_Obj *target_subst, *deps_subst;
17 const char *recipe = NULL;
18 int i, numtargs, numdeps;
19 const char *fmt = "proc recipe::%s {TARGET INPUTS OODATE} { \
20 %s\
21 }";
22 int len = 0;
23 char *cmd = NULL;
24 int ret = JIM_ERR;
26 /* check to make sure we got the information we need */
27 if (argc < 3 || argc > 4) {
28 Jim_WrongNumArgs(interp, 2, argv, "rule target-list dep-list ?script?");
29 return (JIM_ERR);
32 /* If we've got a recipe, store it */
33 if (argc == 4) {
34 recipe = Jim_String(argv[3]);
37 /* Perform variable substitution in the dependency lists */
38 Jim_SubstObj(interp, argv[2], &deps_subst, 0);
40 /* Get all the dependencies and store them in a dep list */
41 numdeps = Jim_ListLength(interp, deps_subst);
42 for (i = 0; i < numdeps; i++) {
43 Jim_Obj *dep = Jim_ListGetIndex(interp, deps_subst, i);
44 const char *sdep = Jim_String(dep);
46 deps = target_cons(sdep, deps);
49 /* Perform variable substitution in the target list */
50 Jim_SubstObj(interp, argv[1], &target_subst, 0);
52 numtargs = Jim_ListLength(interp, target_subst);
54 if (numtargs == 0) {
55 fprintf(stderr, "ERROR: no targets specified for rule\n");
56 free(deps);
57 return (JIM_ERR);
60 /* For each target in the list, create a rule and a proc */
61 for (i = 0; i < numtargs; i++) {
62 Jim_Obj *target_obj = Jim_ListGetIndex(interp, target_subst, i);
63 const char *target = Jim_String(target_obj);
65 /* check if there's already a rule for this target */
66 rule = find_rule(target, tm_rules);
67 if (rule) {
68 /* if so, overwrite it with the new rule */
69 free_target_list(rule->deps);
70 free(rule->recipe);
71 rule->deps = target_list_copy(deps);
72 if (recipe) {
73 rule->recipe = malloc(strlen(recipe) + 1);
74 strcpy(rule->recipe, recipe);
75 } else {
76 rule->recipe = NULL;
78 rule->type = TM_EXPLICIT;
79 } else {
80 /* or else create a new rule */
81 rule = new_rule(target, deps, recipe);
82 tm_rules = rule_cons(rule, tm_rules);
83 free_rule(rule);
86 /* Do we need to set the default goal? */
87 if (tm_goal == NULL) {
88 const char *fmt_set = "set TM_CURRENT_GOAL %s";
90 tm_goal = malloc(strlen(target) + 1);
91 strcpy(tm_goal, target);
93 len = strlen(fmt_set) + strlen(target) + 1;
94 cmd = malloc(len);
95 sprintf(cmd, fmt_set, target);
96 ret = Jim_Eval(interp, cmd);
97 free(cmd);
98 if (ret != (JIM_OK)) {
99 goto error;
103 /* Create a proc representing this rule */
104 len = strlen(fmt) + strlen(target) + (recipe ? strlen(recipe) : 0) + 1;
105 cmd = malloc(len);
106 sprintf(cmd, fmt, target, recipe ? recipe : "");
107 ret = Jim_Eval(interp, cmd);
108 free(cmd);
109 if (ret != (JIM_OK)) {
110 goto error;
114 free_target_list(deps);
115 return (JIM_OK);
117 error:
118 free_target_list(deps);
119 return ret;
122 /* Provide tm_crypto functionality to Jim Tcl */
123 static int sha1sumCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
125 char hash[CRYPTO_HASH_STRING_LENGTH];
126 unsigned char digest[CRYPTO_HASH_SIZE];
127 const char *subcmd = NULL;
128 const char *string = NULL;
130 if (argc != 3) {
131 Jim_WrongNumArgs(interp, 2, argv, "sha1sum \"file\"|\"string\" <filename>|<string>");
132 return (JIM_ERR);
135 subcmd = Jim_String(argv[1]);
136 string = Jim_String(argv[2]);
138 if (strcmp(subcmd, "file") == 0) {
139 TM_CRYPTO_HASH_FILE(string, digest);
140 } else if (strcmp(subcmd, "string") == 0) {
141 TM_CRYPTO_HASH_DATA(string, digest);
142 } else {
143 Jim_WrongNumArgs(interp, 2, argv, "Invalid subcommand for sha1sum (should be \"file\" or \"string\")");
144 return (JIM_ERR);
147 TM_CRYPTO_HASH_TO_STRING(digest, hash);
149 Jim_SetResultString(interp, hash, CRYPTO_HASH_STRING_LENGTH);
151 return (JIM_OK);
155 static int targetCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
157 const char *target = NULL;
159 if (argc != 2) {
160 Jim_WrongNumArgs(interp, 1, argv, "target name");
161 return (JIM_ERR);
164 target = Jim_String(argv[1]);
166 if (find_rule(target, tm_rules)) {
167 Jim_SetResultInt(interp, 1);
168 } else {
169 Jim_SetResultInt(interp, 0);
172 return (JIM_OK);
175 static int commandsCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
177 const char *target = NULL;
178 tm_rule *rule = NULL;
180 if (argc != 2) {
181 Jim_WrongNumArgs(interp, 1, argv, "commands target");
182 return (JIM_ERR);
185 target = Jim_String(argv[1]);
186 rule = find_rule(target, tm_rules);
188 if (rule && rule->recipe) {
189 Jim_SetResultInt(interp, 1);
190 } else {
191 Jim_SetResultInt(interp, 0);
194 return (JIM_OK);
198 * Searches along a of paths for the given package.
200 * Returns the allocated path to the package file if found,
201 * or NULL if not found.
203 static char *tm_FindPackage(Jim_Interp *interp, Jim_Obj *prefixListObj, const char *pkgName)
205 int i;
206 int prefixc = Jim_ListLength(interp, prefixListObj);
208 for (i = 0; i < prefixc; i++) {
209 Jim_Obj *prefixObjPtr = Jim_ListGetIndex(interp, prefixListObj, i);
210 const char *prefix = Jim_String(prefixObjPtr);
211 int len = strlen(prefix) + strlen(pkgName) + 2;
212 char *buf = Jim_Alloc(len);
214 if (strcmp(prefix, ".") == 0) {
215 sprintf(buf, "%s", pkgName);
216 } else {
217 sprintf(buf, "%s/%s", prefix, pkgName);
220 if (access(buf, R_OK) == 0) {
221 return buf;
224 Jim_Free(buf);
226 return NULL;
229 static int includeCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
231 int ret = JIM_ERR;
232 const char *filename = NULL;
233 Jim_Obj *incpath = Jim_GetGlobalVariableStr(interp, TM_INCLUDE_PATH, JIM_NONE);
235 if (argc != 2) {
236 Jim_WrongNumArgs(interp, 1, argv, "include filename");
237 return (JIM_ERR);
240 filename = Jim_String(argv[1]);
242 if (incpath) {
243 char *path = NULL;
244 path = tm_FindPackage(interp, incpath, filename);
245 if (path) {
246 Jim_IncrRefCount(incpath);
247 ret = Jim_EvalFileGlobal(interp, path);
248 Jim_DecrRefCount(interp, incpath);
250 Jim_Free(path);
251 } else {
252 return JIM_ERR;
255 return ret;
259 void tm_RegisterCoreCommands(Jim_Interp *interp)
261 Jim_CreateCommand(interp, "rule", ruleCmd, NULL, NULL);
262 Jim_CreateCommand(interp, "include", includeCmd, NULL, NULL);
263 Jim_CreateCommand(interp, "target", targetCmd, NULL, NULL);
264 Jim_CreateCommand(interp, "commands", commandsCmd, NULL, NULL);
265 Jim_CreateCommand(interp, "sha1sum", sha1sumCmd, NULL, NULL);