gwenhywfar  5.14.1
p_dependencies.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Mon Feb 08 2021
3  copyright : (C) 2021 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * Please see toplevel file COPYING for license details *
8  ***************************************************************************/
9 
10 #ifdef HAVE_CONFIG_H
11 # include <config.h>
12 #endif
13 
14 
17 
18 #include <gwenhywfar/debug.h>
19 #include <gwenhywfar/process.h>
20 #include <gwenhywfar/text.h>
21 #include <gwenhywfar/syncio.h>
22 
23 #include <unistd.h>
24 #include <ctype.h>
25 
26 
27 
28 static int _parseChildNodes(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode);
29 static int _parseDep(GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode);
30 
31 static int _checkVersion(GWEN_DB_NODE *db,
32  const char *sId,
33  const char *sName,
34  const char *sMinVersion,
35  const char *sMaxVersion);
36 static int _retrieveCflags(GWEN_DB_NODE *db, const char *sId, const char *sName);
37 static int _retrieveLdflags(GWEN_DB_NODE *db, const char *sId, const char *sName);
38 static int _callPkgConfig(GWEN_DB_NODE *db,
39  const char *sId,
40  const char *sName,
41  const char *suffix,
42  const char *args);
43 
44 static void _replaceControlCharsWithBlanks(char *ptr);
45 static int _retrieveVariables(GWB_CONTEXT *currentContext, GWEN_DB_NODE *db, const char *sId, const char *sName, GWEN_XMLNODE *xmlNode);
46 static int _retrieveVariable(GWEN_DB_NODE *db, const char *sId, const char *sName, const char *variableName);
47 
48 
49 
50 
51 
52 
53 int GWB_ParseDependencies(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
54 {
55  int rv;
56 
57  rv=_parseChildNodes(project, currentContext, xmlNode);
58  if (rv<0) {
59  DBG_INFO(NULL, "here (%d)", rv);
60  return rv;
61  }
62 
63  return 0;
64 }
65 
66 
67 
68 int _parseChildNodes(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
69 {
70  GWEN_XMLNODE *n;
71 
72  n=GWEN_XMLNode_GetFirstTag(xmlNode);
73  while (n) {
74  const char *name;
75 
76  name=GWEN_XMLNode_GetData(n);
77  if (name && *name) {
78  int rv;
79 
80  DBG_DEBUG(NULL, "Handling element \"%s\"", name);
81 
82  if (strcasecmp(name, "subdirs")==0)
83  rv=GWB_Parser_ParseSubdirs(project, currentContext, n, _parseChildNodes);
84  else if (strcasecmp(name, "dep")==0)
85  rv=_parseDep(currentContext, n);
86  else
87  rv=GWB_Parser_ParseWellKnownElements(project, currentContext, n, _parseChildNodes);
88  if (rv<0) {
89  DBG_ERROR(GWEN_LOGDOMAIN, "Error in element \"%s\", aborting", name);
90  return rv;
91  }
92  }
93 
95  }
96 
97  return 0;
98 }
99 
100 
101 
102 int _parseDep(GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
103 {
104  int rv;
105  const char *s;
106  const char *sId;
107  const char *sName;
108  const char *sMinVersion;
109  const char *sMaxVersion;
110  int required;
111 
112  rv=GWEN_XMLNode_ExpandProperties(xmlNode, GWB_Context_GetVars(currentContext));
113  if (rv<0) {
114  DBG_INFO(NULL, "here (%d)", rv);
115  return rv;
116  }
117 
118  sId=GWEN_XMLNode_GetProperty(xmlNode, "prefix", NULL);
119  if (!(sId && *sId))
120  sId=GWEN_XMLNode_GetProperty(xmlNode, "id", NULL);
121 
122  sName=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
123  if (!(sName && *sName)) {
124  DBG_ERROR(NULL, "Dependency has no name");
125  return GWEN_ERROR_GENERIC;
126  }
127 
128  if (!(sId && *sId)) /* use name if no id/prefix given */
129  sId=sName;
130 
131  s=GWEN_XMLNode_GetProperty(xmlNode, "required", "FALSE");
132  required=(strcasecmp(s, "TRUE")==0)?1:0;
133 
134  sMinVersion=GWEN_XMLNode_GetProperty(xmlNode, "minversion", NULL);
135  sMaxVersion=GWEN_XMLNode_GetProperty(xmlNode, "maxversion", NULL);
136 
137  rv=_checkVersion(GWB_Context_GetVars(currentContext),
138  sId,
139  sName,
140  sMinVersion,
141  sMaxVersion);
142  if (rv==0) {
143  GWEN_XMLNODE *n;
144 
145  rv=_retrieveCflags(GWB_Context_GetVars(currentContext), sId, sName);
146  if (rv<0) {
147  DBG_INFO(NULL, "here (%d)", rv);
148  return rv;
149  }
150  rv=_retrieveLdflags(GWB_Context_GetVars(currentContext), sId, sName);
151  if (rv<0) {
152  DBG_INFO(NULL, "here (%d)", rv);
153  return rv;
154  }
155 
156  n=GWEN_XMLNode_FindFirstTag(xmlNode, "variables", NULL, NULL);
157  if (n) {
158  rv=_retrieveVariables(currentContext, GWB_Context_GetVars(currentContext), sId, sName, n);
159  if (rv<0) {
160  DBG_INFO(NULL, "here (%d)", rv);
161  return rv;
162  }
163  }
164  }
165  else if (rv==GWEN_ERROR_NOT_FOUND) {
166  if (required) {
167  DBG_ERROR(NULL, "Dependency \"%s\" not found but required", sName);
168  return rv;
169  }
170  }
171  else {
172  DBG_INFO(NULL, "here (%d)", rv);
173  return rv;
174  }
175 
176  return 0;
177 }
178 
179 
180 
181 int _retrieveVariables(GWB_CONTEXT *currentContext, GWEN_DB_NODE *db, const char *sId, const char *sName, GWEN_XMLNODE *xmlNode)
182 {
183  GWEN_STRINGLIST *slVariables;
184 
185  slVariables=GWB_Parser_ReadXmlDataIntoStringList(GWB_Context_GetVars(currentContext), xmlNode, 1);
186  if (slVariables) {
188 
189  se=GWEN_StringList_FirstEntry(slVariables);
190  while(se) {
191  const char *s;
192 
194  if (s && *s) {
195  int rv;
196 
197  rv=_retrieveVariable(db, sId, sName, s);
198  if (rv<0) {
199  DBG_ERROR(NULL, "Error retrieving variable \"%s\" for dependency \"%s\"", s, sId);
200  GWEN_StringList_free(slVariables);
201  return rv;
202  }
203  }
205  }
206  }
207 
208  return 0;
209 }
210 
211 
212 
214  const char *sId,
215  const char *sName,
216  const char *sMinVersion,
217  const char *sMaxVersion)
218 {
219  GWEN_BUFFER *argBuffer;
220  GWEN_BUFFER *stdOutBuffer;
221  GWEN_BUFFER *stdErrBuffer;
222  int rv;
223 
224  stdOutBuffer=GWEN_Buffer_new(0, 256, 0, 1);
225  stdErrBuffer=GWEN_Buffer_new(0, 256, 0, 1);
226  argBuffer=GWEN_Buffer_new(0, 256, 0, 1);
227 
228  if (sMinVersion) {
229  GWEN_Buffer_AppendString(argBuffer, " --atleast-version=");
230  GWEN_Buffer_AppendString(argBuffer, sMinVersion);
231  GWEN_Buffer_AppendString(argBuffer, " ");
232  }
233  if (sMaxVersion) {
234  GWEN_Buffer_AppendString(argBuffer, " --max-version=");
235  GWEN_Buffer_AppendString(argBuffer, sMaxVersion);
236  GWEN_Buffer_AppendString(argBuffer, " ");
237  }
238  GWEN_Buffer_AppendString(argBuffer, sName);
239 
240  DBG_DEBUG(NULL, "Running command with args: [%s]", GWEN_Buffer_GetStart(argBuffer));
242  stdOutBuffer, stdErrBuffer);
243  if (rv<0) {
244  DBG_ERROR(NULL, "Error running pkg-config (%d)", rv);
245  GWEN_Buffer_free(argBuffer);
246  GWEN_Buffer_free(stdErrBuffer);
247  GWEN_Buffer_free(stdOutBuffer);
248  return rv;
249  }
250  GWEN_Buffer_free(argBuffer);
251  GWEN_Buffer_free(stdErrBuffer);
252  GWEN_Buffer_free(stdOutBuffer);
253 
254  GWB_Parser_SetItemValue(db, sId, "_EXISTS", (rv==0)?"TRUE":"FALSE");
255  fprintf(stdout, " dep %s: %s\n", sId, (rv==0)?"found":"not found");
256 
257  return (rv==0)?0:GWEN_ERROR_NOT_FOUND;
258 }
259 
260 
261 
262 int _retrieveCflags(GWEN_DB_NODE *db, const char *sId, const char *sName)
263 {
264  int rv;
265 
266  rv=_callPkgConfig(db, sId, sName, "_CFLAGS", "--cflags");
267  if (rv<0) {
268  DBG_ERROR(NULL, "Error running pkg-config (%d)", rv);
269  return rv;
270  }
271 
272  return 0;
273 }
274 
275 
276 
277 int _retrieveLdflags(GWEN_DB_NODE *db, const char *sId, const char *sName)
278 {
279  int rv;
280 
281  rv=_callPkgConfig(db, sId, sName, "_LIBS", "--libs");
282  if (rv<0) {
283  DBG_ERROR(NULL, "Error running pkg-config (%d)", rv);
284  return rv;
285  }
286 
287  return 0;
288 }
289 
290 
291 
292 int _retrieveVariable(GWEN_DB_NODE *db, const char *sId, const char *sName, const char *variableName)
293 {
294  int rv;
295  GWEN_BUFFER *varArgBuffer;
296  GWEN_BUFFER *varSuffixBuffer;
297  const char *s;
298 
299  varArgBuffer=GWEN_Buffer_new(0, 256, 0, 1);
300  GWEN_Buffer_AppendString(varArgBuffer, "--variable=");
301  GWEN_Buffer_AppendString(varArgBuffer, variableName);
302 
303  varSuffixBuffer=GWEN_Buffer_new(0, 256, 0, 1);
304  GWEN_Buffer_AppendString(varSuffixBuffer, "_");
305  s=variableName;
306  while(*s)
307  GWEN_Buffer_AppendByte(varSuffixBuffer, toupper(*(s++)));
308 
309  rv=_callPkgConfig(db, sId, sName, GWEN_Buffer_GetStart(varSuffixBuffer), GWEN_Buffer_GetStart(varArgBuffer));
310  GWEN_Buffer_free(varSuffixBuffer);
311  GWEN_Buffer_free(varArgBuffer);
312  if (rv<0) {
313  DBG_ERROR(NULL, "Error running pkg-config (%d)", rv);
314  return rv;
315  }
316 
317  return 0;
318 }
319 
320 
321 
323  const char *sId,
324  const char *sName,
325  const char *suffix,
326  const char *args)
327 {
328  GWEN_BUFFER *argBuffer;
329  GWEN_BUFFER *stdOutBuffer;
330  GWEN_BUFFER *stdErrBuffer;
331  int rv;
332 
333  stdOutBuffer=GWEN_Buffer_new(0, 256, 0, 1);
334  stdErrBuffer=GWEN_Buffer_new(0, 256, 0, 1);
335  argBuffer=GWEN_Buffer_new(0, 256, 0, 1);
336 
337  GWEN_Buffer_AppendString(argBuffer, args);
338  GWEN_Buffer_AppendString(argBuffer, " ");
339  GWEN_Buffer_AppendString(argBuffer, sName);
340 
341  DBG_DEBUG(NULL, "Running command with args: [%s]", GWEN_Buffer_GetStart(argBuffer));
342  rv=GWEN_Process_RunCommandWaitAndGather("pkg-config", GWEN_Buffer_GetStart(argBuffer), stdOutBuffer, stdErrBuffer);
343  if (rv<0) {
344  DBG_ERROR(NULL, "Error running pkg-config (%d)", rv);
345  GWEN_Buffer_free(argBuffer);
346  GWEN_Buffer_free(stdErrBuffer);
347  GWEN_Buffer_free(stdOutBuffer);
348  return rv;
349  }
350  GWEN_Buffer_free(argBuffer);
351 
353  GWEN_Text_CondenseBuffer(stdOutBuffer);
354  GWB_Parser_SetItemValue(db, sId, suffix, GWEN_Buffer_GetStart(stdOutBuffer));
355 
356  GWEN_Buffer_free(stdErrBuffer);
357  GWEN_Buffer_free(stdOutBuffer);
358  return 0;
359 }
360 
361 
362 
364 {
365  while(ptr && *ptr) {
366  if (*ptr<32)
367  *ptr=32;
368  ptr++;
369  }
370 }
371 
372 
373 
static int _retrieveVariable(GWEN_DB_NODE *db, const char *sId, const char *sName, const char *variableName)
#define DBG_ERROR(dbg_logger, format,...)
Definition: debug.h:97
GWEN_STRINGLIST * GWB_Parser_ReadXmlDataIntoStringList(GWEN_DB_NODE *db, GWEN_XMLNODE *xmlNode, int ignoreDupes)
Definition: parser.c:283
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
struct GWEN_STRINGLISTENTRYSTRUCT GWEN_STRINGLISTENTRY
Definition: stringlist.h:53
void GWEN_Text_CondenseBuffer(GWEN_BUFFER *buf)
Definition: text.c:1620
struct GWB_CONTEXT GWB_CONTEXT
Definition: context.h:17
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
static int _callPkgConfig(GWEN_DB_NODE *db, const char *sId, const char *sName, const char *suffix, const char *args)
#define DBG_DEBUG(dbg_logger, format,...)
Definition: debug.h:214
const char * GWEN_XMLNode_GetProperty(const GWEN_XMLNODE *n, const char *name, const char *defaultValue)
Definition: xml.c:239
GWENHYWFAR_API int GWEN_Process_RunCommandWaitAndGather(const char *prg, const char *args, GWEN_BUFFER *stdOutBuffer, GWEN_BUFFER *stdErrBuffer)
Definition: process_all.c:31
#define NULL
Definition: binreloc.c:300
static int _retrieveCflags(GWEN_DB_NODE *db, const char *sId, const char *sName)
struct GWB_PROJECT GWB_PROJECT
Definition: project.h:14
#define GWEN_LOGDOMAIN
Definition: logger.h:32
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
GWEN_STRINGLISTENTRY * GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:390
static int _checkVersion(GWEN_DB_NODE *db, const char *sId, const char *sName, const char *sMinVersion, const char *sMaxVersion)
int GWB_Parser_ParseSubdirs(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode, GWB_PARSER_PARSE_ELEMENT_FN fn)
Definition: parser.c:367
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:406
int GWB_Parser_ParseWellKnownElements(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *n, GWB_PARSER_PARSE_ELEMENT_FN fn)
Definition: parser.c:942
static void _replaceControlCharsWithBlanks(char *ptr)
void GWEN_StringList_free(GWEN_STRINGLIST *sl)
Definition: stringlist.c:62
GWEN_XMLNODE * GWEN_XMLNode_FindFirstTag(const GWEN_XMLNODE *n, const char *tname, const char *pname, const char *pvalue)
Definition: xml.c:776
GWEN_DB_NODE * GWB_Context_GetVars(const GWB_CONTEXT *ctx)
Definition: context.c:427
GWEN_XMLNODE * GWEN_XMLNode_GetNextTag(const GWEN_XMLNODE *n)
Definition: xml.c:712
static int _retrieveVariables(GWB_CONTEXT *currentContext, GWEN_DB_NODE *db, const char *sId, const char *sName, GWEN_XMLNODE *xmlNode)
struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST
Definition: stringlist.h:56
static int _parseChildNodes(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
#define GWEN_ERROR_GENERIC
Definition: error.h:62
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:393
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
int GWB_ParseDependencies(GWB_PROJECT *project, GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
GWEN_XMLNODE * GWEN_XMLNode_GetFirstTag(const GWEN_XMLNODE *n)
Definition: xml.c:705
const char * GWEN_XMLNode_GetData(const GWEN_XMLNODE *n)
Definition: xml.c:370
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:398
#define GWEN_ERROR_NOT_FOUND
Definition: error.h:89
void GWB_Parser_SetItemValue(GWEN_DB_NODE *db, const char *sId, const char *suffix, const char *value)
Definition: parser.c:856
static int _parseDep(GWB_CONTEXT *currentContext, GWEN_XMLNODE *xmlNode)
int GWEN_XMLNode_ExpandProperties(const GWEN_XMLNODE *n, GWEN_DB_NODE *dbVars)
Definition: xml.c:634
#define DBG_INFO(dbg_logger, format,...)
Definition: debug.h:181
struct GWEN__XMLNODE GWEN_XMLNODE
Definition: xml.h:156
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:992
static int _retrieveLdflags(GWEN_DB_NODE *db, const char *sId, const char *sName)