Imported Upstream version 0.18.1.1
[platform/upstream/gettext.git] / gettext-tools / src / msgl-header.c
1 /* Message list header manipulation.
2    Copyright (C) 2007 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2007.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 /* Specification.  */
24 #include "msgl-header.h"
25
26 #include <string.h>
27
28 #include "xalloc.h"
29
30 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
31
32
33 void
34 msgdomain_list_set_header_field (msgdomain_list_ty *mdlp,
35                                  const char *field, const char *value)
36 {
37   /* The known fields in their usual order.  */
38   static const struct
39     {
40       const char *name;
41       size_t len;
42     }
43   known_fields[] =
44     {
45       { "Project-Id-Version:", sizeof ("Project-Id-Version:") - 1 },
46       { "Report-Msgid-Bugs-To:", sizeof ("Report-Msgid-Bugs-To:") - 1 },
47       { "POT-Creation-Date:", sizeof ("POT-Creation-Date:") - 1 },
48       { "PO-Revision-Date:", sizeof ("PO-Revision-Date:") - 1 },
49       { "Last-Translator:", sizeof ("Last-Translator:") - 1 },
50       { "Language-Team:", sizeof ("Language-Team:") - 1 },
51       { "Language:", sizeof ("Language:") - 1 },
52       { "MIME-Version:", sizeof ("MIME-Version:") - 1 },
53       { "Content-Type:", sizeof ("Content-Type:") - 1 },
54       { "Content-Transfer-Encoding:",
55         sizeof ("Content-Transfer-Encoding:") - 1 }
56     };
57   size_t field_len;
58   int field_index;
59   size_t k, i;
60
61   field_len = strlen (field);
62
63   /* Search the field in known_fields[].  */
64   field_index = -1;
65   for (k = 0; k < SIZEOF (known_fields); k++)
66     if (strcmp (known_fields[k].name, field) == 0)
67       {
68         field_index = k;
69         break;
70       }
71
72   for (i = 0; i < mdlp->nitems; i++)
73     {
74       message_list_ty *mlp = mdlp->item[i]->messages;
75       size_t j;
76
77       /* Search the header entry.  */
78       for (j = 0; j < mlp->nitems; j++)
79         if (is_header (mlp->item[j]) && !mlp->item[j]->obsolete)
80           {
81             message_ty *mp = mlp->item[j];
82
83             /* Modify the header entry.  */
84             const char *header = mp->msgstr;
85             char *new_header =
86               XNMALLOC (strlen (header) + 1
87                         + strlen (field) + 1 + strlen (value) + 1 + 1,
88                         char);
89
90             /* Test whether the field already occurs in the header entry.  */
91             const char *h;
92
93             for (h = header; *h != '\0'; )
94               {
95                 if (strncmp (h, field, field_len) == 0)
96                   break;
97                 h = strchr (h, '\n');
98                 if (h == NULL)
99                   break;
100                 h++;
101               }
102             if (h != NULL && *h != '\0')
103               {
104                 /* Replace the field.  */
105                 char *p = new_header;
106                 memcpy (p, header, h - header);
107                 p += h - header;
108                 p = stpcpy (p, field);
109                 p = stpcpy (stpcpy (stpcpy (p, " "), value), "\n");
110                 h = strchr (h, '\n');
111                 if (h != NULL)
112                   {
113                     h++;
114                     stpcpy (p, h);
115                   }
116               }
117             else if (field_index < 0)
118               {
119                 /* An unknown field.  Append it at the end.  */
120                 char *p = new_header;
121                 p = stpcpy (p, header);
122                 if (p > new_header && p[-1] != '\n')
123                   *p++ = '\n';
124                 p = stpcpy (p, field);
125                 stpcpy (stpcpy (stpcpy (p, " "), value), "\n");
126               }
127             else
128               {
129                 /* Find the appropriate position for inserting the field.  */
130                 for (h = header; *h != '\0'; )
131                   {
132                     /* Test whether h starts with a field name whose index is
133                        > field_index.  */
134                     for (k = field_index + 1; k < SIZEOF (known_fields); k++)
135                       if (strncmp (h, known_fields[k].name, known_fields[k].len)
136                           == 0)
137                         break;
138                     if (k < SIZEOF (known_fields))
139                       break;
140                     h = strchr (h, '\n');
141                     if (h == NULL)
142                       break;
143                     h++;
144                   }
145                 if (h != NULL && *h != '\0')
146                   {
147                     /* Insert the field at position h.  */
148                     char *p = new_header;
149                     memcpy (p, header, h - header);
150                     p += h - header;
151                     p = stpcpy (p, field);
152                     p = stpcpy (stpcpy (stpcpy (p, " "), value), "\n");
153                     stpcpy (p, h);
154                   }
155                 else
156                   {
157                     /* Append it at the end.  */
158                     char *p = new_header;
159                     p = stpcpy (p, header);
160                     if (p > new_header && p[-1] != '\n')
161                       *p++ = '\n';
162                     p = stpcpy (p, field);
163                     stpcpy (stpcpy (stpcpy (p, " "), value), "\n");
164                   }
165               }
166
167             mp->msgstr = new_header;
168           }
169     }
170 }