Line data Source code
1 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 : /*
3 : * reg2xml.c
4 : * Copyright (C) 2011-2012 Akira TAGOH
5 : *
6 : * Authors:
7 : * Akira TAGOH <akira@tagoh.org>
8 : *
9 : * You may distribute under the terms of either the GNU
10 : * Lesser General Public License or the Mozilla Public
11 : * License, as specified in the README file.
12 : */
13 : #ifdef HAVE_CONFIG_H
14 : #include "config.h"
15 : #endif
16 :
17 : #include <string.h>
18 : #include <libxml/tree.h>
19 : #include "lt-messages.h"
20 : #include "lt-utils.h"
21 :
22 : #ifdef _WIN32
23 : static char *
24 : strndup(const char *string,size_t s)
25 : {
26 : const char *p;
27 : char *r;
28 : if (!string)
29 : return NULL;
30 : p = string;
31 : while (s) {
32 : if (!*p)
33 : break;
34 : p++;
35 : s--;
36 : }
37 : s = (p - string);
38 : r = malloc(1+s);
39 : if (r) {
40 : strncpy(r,string,s);
41 : r[s] = 0;
42 : }
43 : return r;
44 : }
45 : #endif
46 :
47 : /*< private >*/
48 : static char *
49 0 : _drop_crlf(char *string)
50 : {
51 : size_t len, i;
52 :
53 0 : lt_return_val_if_fail (string != NULL, NULL);
54 0 : lt_return_val_if_fail (string[0] != 0, NULL);
55 :
56 0 : len = strlen(string);
57 0 : for (i = len - 1; i > 0; i--) {
58 0 : if (string[i] == '\r' ||
59 0 : string[i] == '\n') {
60 0 : string[i] = 0;
61 : } else {
62 : break;
63 : }
64 : }
65 :
66 0 : return string;
67 : }
68 :
69 : static lt_bool_t
70 0 : _parse(const char *filename,
71 : xmlNodePtr root)
72 : {
73 : FILE *fp;
74 : char buffer[1024];
75 0 : lt_bool_t in_entry = FALSE;
76 0 : xmlNodePtr ent = NULL;
77 :
78 0 : if ((fp = fopen(filename, "rb")) == NULL) {
79 0 : lt_critical("Unable to open %s", filename);
80 0 : return FALSE;
81 : }
82 : while (1) {
83 0 : fgets(buffer, 1024, fp);
84 0 : if (feof(fp))
85 0 : break;
86 0 : _drop_crlf(buffer);
87 0 : if (lt_strcmp0(buffer, "%%") == 0) {
88 0 : if (in_entry) {
89 0 : if (ent) {
90 0 : xmlAddChild(root, ent);
91 : }
92 0 : ent = NULL;
93 : }
94 0 : in_entry = TRUE;
95 : } else {
96 0 : if (!in_entry) {
97 : /* ignore it */
98 0 : continue;
99 : }
100 0 : if (strncmp(buffer, "Type: ", 6) == 0) {
101 0 : if (ent) {
102 0 : lt_warning("Duplicate entry type: line = '%s', current type = '%s'",
103 : buffer, ent->name);
104 : } else {
105 0 : ent = xmlNewNode(NULL, (const xmlChar *)&buffer[6]);
106 : }
107 : } else {
108 0 : if (!ent) {
109 0 : lt_warning("No entry type: line = '%s'",
110 : buffer);
111 0 : in_entry = FALSE;
112 : } else {
113 : char *token, *tag;
114 : fpos_t pos;
115 : size_t len;
116 :
117 : multiline:
118 0 : fgetpos(fp, &pos);
119 0 : len = strlen(buffer);
120 0 : fgets(&buffer[len], 1024 - len, fp);
121 0 : if (buffer[len] == ' ') {
122 : size_t l, i;
123 :
124 0 : _drop_crlf(&buffer[len]);
125 0 : l = strlen(&buffer[len]);
126 0 : for (i = 1; i < l; i++) {
127 0 : if (buffer[len + i] != ' ')
128 0 : break;
129 : }
130 0 : if (i > 1) {
131 0 : memmove(&buffer[len + 1], &buffer[len + i], l - i);
132 : }
133 0 : goto multiline;
134 : } else {
135 0 : buffer[len] = 0;
136 0 : fsetpos(fp, &pos);
137 : }
138 0 : token = strstr(buffer, ": ");
139 0 : tag = strndup(buffer, token - buffer);
140 0 : token += 2;
141 0 : xmlNewChild(ent, NULL,
142 0 : (const xmlChar *)lt_strlower(tag),
143 : (const xmlChar *)token);
144 0 : free(tag);
145 : }
146 : }
147 : }
148 0 : }
149 :
150 0 : return TRUE;
151 : }
152 :
153 : static lt_bool_t
154 0 : _output_xml(const char *filename,
155 : const char *out_filename)
156 : {
157 : xmlDocPtr doc;
158 : xmlNodePtr root;
159 : lt_bool_t retval;
160 :
161 0 : doc = xmlNewDoc((const xmlChar *)"1.0");
162 0 : root = xmlNewDocNode(doc, NULL,
163 : (const xmlChar *)"registry",
164 : NULL);
165 0 : xmlDocSetRootElement(doc, root);
166 :
167 0 : if (!(retval = _parse(filename, root)))
168 0 : goto bail;
169 :
170 0 : xmlSaveFormatFileEnc(out_filename && out_filename[0] != '-' ? out_filename : "-",
171 : doc, "UTF-8", 1);
172 : bail:
173 0 : xmlFreeDoc(doc);
174 :
175 0 : return retval;
176 : }
177 :
178 : /*< public >*/
179 : int
180 0 : main(int argc,
181 : char **argv)
182 : {
183 0 : if (argc < 3)
184 0 : return 1;
185 :
186 0 : if (!_output_xml(argv[1], argv[2]))
187 0 : return 1;
188 :
189 0 : return 0;
190 : }
|