1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2004 Sebastien 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 * Execute autogen program
24 * This takes cares of everything needed to run autogen:
25 * - generate the definition files from a list of values
26 * - add autogen marker in template file if necessary
27 * - check autogen version
28 * - run autogen with AnjutaLauncher object
29 * Autogen output could be written in a file or pass to callback function.
30 *---------------------------------------------------------------------------*/
36 #include <libanjuta/anjuta-launcher.h>
38 #include <glib/gstdio.h>
39 #include <glib/gfileutils.h>
40 #include <glib/gstrfuncs.h>
45 #include <glib/gstdio.h>
47 /*---------------------------------------------------------------------------*/
49 #define TMP_DEF_FILENAME "NPWDEFXXXXXX"
50 #define TMP_TPL_FILENAME "NPWTPLXXXXXX"
52 #define FILE_BUFFER_SIZE 4096
54 /*---------------------------------------------------------------------------*/
58 gchar
* deffilename
; /* name of generated definition file */
59 const gchar
* tplfilename
; /* name of template (input) file */
60 gchar
* temptplfilename
; /* name of generated template if the
61 * previous file doesn't contains
64 /* Output file name and handle used
65 * when autogen output is written
67 const gchar
* outfilename
;
70 /* Call back function and data used
71 * when autogen output something */
72 NPWAutogenOutputFunc outfunc
;
74 /* Call back function and data used
75 * when autogen terminate */
76 NPWAutogenFunc endfunc
;
79 AnjutaLauncher
* launcher
;
80 gboolean busy
; /* For debugging */
83 /*---------------------------------------------------------------------------*/
86 *---------------------------------------------------------------------------*/
88 /* Check if autogen version 5 is present */
91 npw_check_autogen (void)
93 gchar
* args
[] = {"autogen", "-v", NULL
};
96 if (g_spawn_sync (NULL
, args
, NULL
, G_SPAWN_SEARCH_PATH
| G_SPAWN_STDERR_TO_DEV_NULL
,
97 NULL
, NULL
, &output
, NULL
, NULL
, NULL
))
103 if (strstr(output
, "The Automated Program Generator") == NULL
) return FALSE
;
105 /* Get version number */
106 ptr
= strstr(output
, "Ver. ");
107 if (ptr
== NULL
) return FALSE
;
109 sscanf(ptr
,"%d.%d.%d", &ver
[0], &ver
[1], &ver
[2]);
111 return (ver
[0] == 5);
118 *---------------------------------------------------------------------------*/
121 cb_autogen_write_definition (const gchar
* name
, const gchar
* value
, NPWValueTag tag
, gpointer user_data
)
123 FILE* def
= (FILE *)user_data
;
125 if ((tag
& NPW_VALID_VALUE
) && (value
!= NULL
))
127 if(value
[0] == '{') /* Seems to be a list, so do not quote */
129 fprintf(def
, "%s = %s;\n", name
, value
);
133 gchar
*esc_value
= g_strescape (value
, NULL
);
134 fprintf (def
, "%s = \"%s\";\n", name
, esc_value
);
141 npw_autogen_write_definition_file (NPWAutogen
* this, NPWValueHeap
* values
)
145 /* Autogen should not be running */
146 g_return_val_if_fail (this->busy
== FALSE
, FALSE
);
148 def
= fopen (this->deffilename
, "wt");
149 if (def
== NULL
) return FALSE
;
151 /* Generate definition data for autogen */
152 fputs ("AutoGen Definitions .;\n",def
);
153 npw_value_heap_foreach_value (values
, cb_autogen_write_definition
, def
);
160 /* Set input and output
161 *---------------------------------------------------------------------------*/
164 npw_autogen_set_input_file (NPWAutogen
* this, const gchar
* filename
, const gchar
* start_marker
, const gchar
* end_marker
)
172 /* Autogen should not be running */
173 g_return_val_if_fail (this->busy
== FALSE
, FALSE
);
175 /* We need to specify start and end marker or nothing */
176 g_return_val_if_fail ((start_marker
&& end_marker
) || (!start_marker
&& !end_marker
), FALSE
);
178 /* Remove previous temporary file if exist */
179 if (this->temptplfilename
!= NULL
)
181 remove (this->temptplfilename
);
182 g_free (this->temptplfilename
);
183 this->temptplfilename
= NULL
;
186 if ((start_marker
== NULL
) && (end_marker
== NULL
))
188 /* input file is really an autogen file, nothig do to */
189 this->tplfilename
= filename
;
194 /* Autogen definition is missing, we need to create a temporary file
197 /* Create temporary file */
198 this->temptplfilename
= g_build_filename (g_get_tmp_dir (), TMP_TPL_FILENAME
, NULL
);
199 mktemp (this->temptplfilename
);
200 this->tplfilename
= this->temptplfilename
;
201 tpl
= fopen (this->tplfilename
, "wt");
202 if (tpl
== NULL
) return FALSE
;
204 /* Add autogen definition */
205 fputs (start_marker
, tpl
);
206 fputs (" autogen5 template ", tpl
);
207 fputs (end_marker
, tpl
);
210 /* Copy source file into this new file */
211 src
= fopen (filename
, "rb");
212 if (src
== NULL
) return FALSE
;
214 buffer
= g_new (gchar
, FILE_BUFFER_SIZE
);
219 len
= fread (buffer
, 1, FILE_BUFFER_SIZE
, src
);
220 if ((len
!= FILE_BUFFER_SIZE
) && !feof (src
))
226 if (len
!= fwrite (buffer
, 1, len
, tpl
))
241 npw_autogen_set_output_file (NPWAutogen
* this, const gchar
* filename
)
243 /* Autogen should not be running */
244 g_return_val_if_fail (this->busy
== FALSE
, FALSE
);
246 this->outfilename
= filename
;
247 this->outfunc
= NULL
;
253 npw_autogen_set_output_callback (NPWAutogen
* this, NPWAutogenOutputFunc func
, gpointer user_data
)
255 /* Autogen should not be running */
256 g_return_val_if_fail (this->busy
== FALSE
, FALSE
);
258 this->outfunc
= func
;
259 this->outdata
= user_data
;
260 this->outfilename
= NULL
;
266 *---------------------------------------------------------------------------*/
269 on_autogen_output (AnjutaLauncher
* launcher
, AnjutaLauncherOutputType type
, const gchar
* output
, gpointer user_data
)
271 NPWAutogen
* this = (NPWAutogen
*)user_data
;
273 if (this->outfilename
!= NULL
)
275 /* Write output in a file */
276 if (this->output
!= NULL
)
278 fputs (output
, this->output
);
282 if (this->outfunc
!= NULL
)
284 /* Call a callback function */
285 (this->outfunc
)(output
, this->outdata
);
290 on_autogen_terminated (AnjutaLauncher
* launcher
, gint pid
, gint status
, gulong time
, NPWAutogen
* this)
293 if (this->output
!= NULL
)
295 fclose (this->output
);
297 /* Delete empty file */
298 if (this->empty
== TRUE
)
300 g_remove (this->outfilename
);
306 (this->endfunc
)(this, this->enddata
);
311 npw_autogen_execute (NPWAutogen
* this, NPWAutogenFunc func
, gpointer data
, GError
** error
)
313 gchar
* args
[] = {"autogen", "-T", NULL
, NULL
, NULL
};
315 /* Autogen should not be running */
316 g_return_val_if_fail (this->busy
== FALSE
, FALSE
);
317 g_return_val_if_fail (this, FALSE
);
318 g_return_val_if_fail (this->launcher
, FALSE
);
320 /* Set output end callback */
323 this->endfunc
= func
;
324 this->enddata
= data
;
328 this->endfunc
= NULL
;
330 args
[2] = (gchar
*)this->tplfilename
;
331 args
[3] = (gchar
*)this->deffilename
;
333 /* Check if output file can be written */
334 if (this->outfilename
!= NULL
)
336 /* Open file if it's not already done */
337 this->output
= fopen (this->outfilename
, "wt");
338 if (this->output
== NULL
)
343 g_file_error_from_errno(errno
),
344 "Could not open file \"%s\": %s",
355 if (!anjuta_launcher_execute_v (this->launcher
, args
, NULL
, on_autogen_output
, this))
359 /* Keep output as it is */
360 anjuta_launcher_set_encoding (this->launcher
, NULL
);
365 /* Creation and Destruction
366 *---------------------------------------------------------------------------*/
368 NPWAutogen
* npw_autogen_new (void)
372 this = g_new0(NPWAutogen
, 1);
374 this->launcher
= anjuta_launcher_new ();
375 g_signal_connect (G_OBJECT (this->launcher
), "child-exited", G_CALLBACK (on_autogen_terminated
), this);
377 /* Create a temporary file for definitions */
378 this->deffilename
= g_build_filename (g_get_tmp_dir (), TMP_DEF_FILENAME
, NULL
);
379 mktemp (this->deffilename
);
384 void npw_autogen_free (NPWAutogen
* this)
386 g_return_if_fail(this != NULL
);
388 if (this->output
!= NULL
)
390 /* output is not used if a callback function is used */
391 fclose (this->output
);
394 if (this->temptplfilename
!= NULL
)
396 /* temptplfilename is not used if input file already
397 * contains autogen marker */
398 remove (this->temptplfilename
);
399 g_free (this->temptplfilename
);
403 /* deffilename should always be here (created in new) */
404 g_return_if_fail (this->deffilename
);
405 remove (this->deffilename
);
406 g_free (this->deffilename
);
408 g_signal_handlers_disconnect_by_func (G_OBJECT (this->launcher
), G_CALLBACK (on_autogen_terminated
), this);
409 g_object_unref (this->launcher
);