1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
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:
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
33 *---------------------------------------------------------------------------*/
38 #include <libanjuta/anjuta-utils.h>
40 #include <glib/gi18n.h>
48 *---------------------------------------------------------------------------*/
51 build_strv_insert_before (gchar
***pstrv
, gint pos
)
54 gchar
**strv
= *pstrv
;
58 /* First argument, allocate memory */
59 strv
= g_new0 (gchar
*, 2);
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
));
75 if (pos
> 0) memcpy(new_strv
, strv
, (sizeof (gchar
*)) * pos
);
88 build_strv_remove (gchar
**strv
, gint pos
)
90 gsize count
= g_strv_length (strv
);
92 g_return_val_if_fail (pos
>= 0, FALSE
);
96 /* Argument does not exist */
103 memcpy (&strv
[pos
], &strv
[pos
+ 1], sizeof(gchar
*) * (count
- pos
));
110 *---------------------------------------------------------------------------*/
113 build_program_find_env (BuildProgram
*prog
, const gchar
*name
)
115 if (prog
->envp
!= NULL
)
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
] == '='))
135 *---------------------------------------------------------------------------*/
138 build_program_set_command (BuildProgram
*prog
, const gchar
*command
)
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
++)
153 new_arg
= anjuta_util_shell_expand (*arg
);
162 build_program_get_basename (BuildProgram
*prog
)
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
;
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
);
184 build_program_insert_arg (BuildProgram
*prog
, gint pos
, const gchar
*arg
)
188 parg
= build_strv_insert_before (&prog
->argv
, pos
);
189 *parg
= anjuta_util_shell_expand (arg
);
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
);
203 g_free (prog
->argv
[pos
]);
204 prog
->argv
[pos
] = anjuta_util_shell_expand (arg
);
211 build_program_remove_arg (BuildProgram
*prog
, gint pos
)
213 return build_strv_remove (prog
->argv
, pos
);
218 build_program_add_env_list (BuildProgram
*prog
, GList
*vars
)
223 for (item
= vars
; item
!= NULL
; item
= g_list_next (item
))
229 name
= g_strdup ((gchar
*)item
->data
);
230 equal
= strchr (name
, '=');
241 ok
= ok
&& build_program_add_env (prog
, name
, value
);
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
);
257 /* Append variable */
258 *build_strv_insert_before (&prog
->envp
, -1) = name_and_value
;
262 g_free (prog
->envp
[found
]);
263 prog
->envp
[found
] = name_and_value
;
269 build_program_remove_env (BuildProgram
*prog
, const gchar
*name
)
271 gint found
= build_program_find_env (prog
, name
);
274 /* Variable not found */
279 return build_strv_remove (prog
->envp
, found
);
284 build_program_override (BuildProgram
*prog
, IAnjutaEnvironment
*env
)
287 GError
* error
= NULL
;
289 if (env
== NULL
) return TRUE
;
291 ok
= ianjuta_environment_override (env
, &prog
->work_dir
, &prog
->argv
, &prog
->envp
, &error
);
295 g_message ("ENV error!");
296 dialog
= gtk_message_dialog_new (NULL
,
300 _("Error while setting up build environment:\n %s"),
302 g_signal_connect (dialog
, "response", G_CALLBACK (gtk_widget_destroy
), NULL
);
303 gtk_widget_show (dialog
);
304 g_error_free (error
);
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 *---------------------------------------------------------------------------*/
330 build_program_new (void)
334 prog
= g_new0 (BuildProgram
, 1);
340 build_program_new_with_command (GFile
*directory
, const gchar
*command
,...)
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
);
357 build_program_set_command (prog
, full_command
);
358 g_free (full_command
);
364 build_program_free (BuildProgram
*prog
)
366 if (prog
->callback
!= NULL
)
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
);
377 g_free (prog
->work_dir
);
378 if (prog
->argv
) g_strfreev (prog
->argv
);
379 if (prog
->envp
) g_strfreev (prog
->envp
);