Initial German translation of the build tutorial
[anjuta.git] / plugins / build-basic-autotools / program.c
blob05dd18f03e3a45de09638dbf786d63d77f551edf
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 program.c
4 Copyright (C) 2008 Sébastien Granjoux
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * This objects is used to keep all data useful to run a program:
23 * - working directory
24 * - program name
25 * - program arguments
26 * - program environment variables
27 * - a callback when program end
29 * It is just a container, so it is not able to run the program by itself, but
30 * all data are available.
31 * It includes some functions to modify the program data, take care of
32 * memory allocation.
33 *---------------------------------------------------------------------------*/
36 #include "program.h"
38 #include <libanjuta/anjuta-utils.h>
40 #include <glib/gi18n.h>
42 #include <string.h>
43 #include <ctype.h>
44 #include <stdarg.h>
47 /* Helper functions
48 *---------------------------------------------------------------------------*/
50 static gchar **
51 build_strv_insert_before (gchar ***pstrv, gint pos)
53 gsize count;
54 gchar **strv = *pstrv;
56 if (strv == NULL)
58 /* First argument, allocate memory */
59 strv = g_new0 (gchar *, 2);
60 pos = 0;
61 count = 1;
63 else
65 gchar **new_strv;
67 /* Increase array */
68 count = g_strv_length (strv);
70 new_strv = g_new (gchar *, count + 2);
71 if ((pos >= 0) && (pos < count))
72 memcpy (&new_strv[pos + 1], &strv[pos], sizeof (gchar *) * (count - pos));
73 else
74 pos = count;
75 if (pos > 0) memcpy(new_strv, strv, (sizeof (gchar *)) * pos);
76 g_free (strv);
77 strv = new_strv;
78 count++;
81 strv[count] = NULL;
82 *pstrv = strv;
84 return &strv[pos];
87 static gboolean
88 build_strv_remove (gchar **strv, gint pos)
90 gsize count = g_strv_length (strv);
92 g_return_val_if_fail (pos >= 0, FALSE);
94 if (pos >= count)
96 /* Argument does not exist */
98 return FALSE;
100 else
102 g_free (strv[pos]);
103 memcpy (&strv[pos], &strv[pos + 1], sizeof(gchar *) * (count - pos));
105 return TRUE;
109 /* Private functions
110 *---------------------------------------------------------------------------*/
112 static gint
113 build_program_find_env (BuildProgram *prog, const gchar *name)
115 if (prog->envp != NULL)
117 gint i;
118 gchar **envp = prog->envp;
119 gsize len = strlen (name);
121 /* Look for an already existing variable */
122 for (i = 0; envp[i] != NULL; i++)
124 if ((strncmp (envp[i], name, len) == 0) && (envp[i][len] == '='))
126 return i;
131 return -1;
134 /* Public functions
135 *---------------------------------------------------------------------------*/
137 gboolean
138 build_program_set_command (BuildProgram *prog, const gchar *command)
140 gboolean ok;
141 gchar **arg;
143 g_return_val_if_fail (prog != NULL, FALSE);
145 if (prog->argv) g_strfreev (prog->argv);
147 /* Store args and environment variables as string array */
148 ok = g_shell_parse_argv (command, NULL, &prog->argv, NULL) ? TRUE : FALSE;
149 for (arg = prog->argv; *arg != NULL; arg++)
151 gchar *new_arg;
153 new_arg = anjuta_util_shell_expand (*arg);
154 g_free (*arg);
155 *arg = new_arg;
158 return ok;
161 const gchar *
162 build_program_get_basename (BuildProgram *prog)
164 const gchar *base;
166 if ((prog->argv == NULL) || (prog->argv[0] == NULL)) return NULL;
168 base = strrchr (prog->argv[0], G_DIR_SEPARATOR);
170 return base == NULL ? prog->argv[0] : base;
174 void
175 build_program_set_working_directory (BuildProgram *prog, GFile *directory)
177 g_free (prog->work_dir);
179 prog->work_dir = g_file_get_path (directory);
183 gboolean
184 build_program_insert_arg (BuildProgram *prog, gint pos, const gchar *arg)
186 gchar **parg;
188 parg = build_strv_insert_before (&prog->argv, pos);
189 *parg = anjuta_util_shell_expand (arg);
191 return TRUE;
194 gboolean
195 build_program_replace_arg (BuildProgram *prog, gint pos, const gchar *arg)
197 if (pos >= g_strv_length (prog->argv))
199 return build_program_insert_arg (prog, pos, arg);
201 else
203 g_free (prog->argv[pos]);
204 prog->argv[pos] = anjuta_util_shell_expand (arg);
207 return TRUE;
210 gboolean
211 build_program_remove_arg (BuildProgram *prog, gint pos)
213 return build_strv_remove (prog->argv, pos);
217 gboolean
218 build_program_add_env_list (BuildProgram *prog, GList *vars)
220 GList *item;
221 gboolean ok = TRUE;
223 for (item = vars; item != NULL; item = g_list_next (item))
225 const gchar *value;
226 gchar *equal;
227 gchar *name;
229 name = g_strdup ((gchar *)item->data);
230 equal = strchr (name, '=');
231 if (equal != NULL)
233 *equal = '\0';
234 value = equal + 1;
236 else
238 value = NULL;
241 ok = ok && build_program_add_env (prog, name, value);
242 g_free (name);
245 return ok;
249 gboolean
250 build_program_add_env (BuildProgram *prog, const gchar *name, const gchar *value)
252 gint found = build_program_find_env (prog, name);
253 gchar *name_and_value = g_strconcat (name, "=", value, NULL);
255 if (found == -1)
257 /* Append variable */
258 *build_strv_insert_before (&prog->envp, -1) = name_and_value;
260 else
262 g_free (prog->envp[found]);
263 prog->envp[found] = name_and_value;
265 return TRUE;
268 gboolean
269 build_program_remove_env (BuildProgram *prog, const gchar *name)
271 gint found = build_program_find_env (prog, name);
272 if (found == -1)
274 /* Variable not found */
275 return FALSE;
277 else
279 return build_strv_remove (prog->envp, found);
283 gboolean
284 build_program_override (BuildProgram *prog, IAnjutaEnvironment *env)
286 gboolean ok;
287 GError* error = NULL;
289 if (env == NULL) return TRUE;
291 ok = ianjuta_environment_override (env, &prog->work_dir, &prog->argv, &prog->envp, &error);
292 if (!ok && error)
294 GtkWidget* dialog;
295 g_message ("ENV error!");
296 dialog = gtk_message_dialog_new (NULL,
298 GTK_MESSAGE_ERROR,
299 GTK_BUTTONS_OK,
300 _("Error while setting up build environment:\n %s"),
301 error->message);
302 g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
303 gtk_widget_show (dialog);
304 g_error_free (error);
306 return ok;
309 void
310 build_program_set_callback (BuildProgram *prog, IAnjutaBuilderCallback callback, gpointer user_data)
312 prog->callback = callback;
313 prog->user_data = user_data;
316 void build_program_callback (BuildProgram *prog, GObject *sender, IAnjutaBuilderHandle handle, GError *err)
318 if (prog->callback != NULL)
320 prog->callback (sender, handle, err, prog->user_data);
321 prog->callback = NULL;
326 /* Constructor & Destructor
327 *---------------------------------------------------------------------------*/
329 BuildProgram*
330 build_program_new (void)
332 BuildProgram *prog ;
334 prog = g_new0 (BuildProgram, 1);
336 return prog;
339 BuildProgram*
340 build_program_new_with_command (GFile *directory, const gchar *command,...)
342 BuildProgram *prog;
343 gchar *full_command;
344 va_list args;
346 prog = build_program_new ();
347 if (prog == NULL) return NULL;
349 build_program_set_working_directory (prog, directory);
351 /* Avoid terminal control sequence */
352 build_program_add_env (prog, "TERM", "dumb");
354 va_start (args, command);
355 full_command = g_strdup_vprintf (command, args);
356 va_end (args);
357 build_program_set_command (prog, full_command);
358 g_free (full_command);
360 return prog;
363 void
364 build_program_free (BuildProgram *prog)
366 if (prog->callback != NULL)
368 GError *err;
370 /* Emit command-finished signal abort */
371 err = g_error_new_literal (ianjuta_builder_error_quark (),
372 IANJUTA_BUILDER_ABORTED,
373 _("Command aborted"));
374 prog->callback (NULL, NULL, err, prog->user_data);
375 g_error_free (err);
377 g_free (prog->work_dir);
378 if (prog->argv) g_strfreev (prog->argv);
379 if (prog->envp) g_strfreev (prog->envp);
380 g_free (prog);