1 /*
2 * ========================================================================
3 * Copyright 2006-2007 University of Washington
4 * Copyright 2013-2021 Eduardo Chappa
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * ========================================================================
13 */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19
20
21 typedef struct helplist {
22 char *name;
23 struct helplist *next;
24 } HELPLIST_S;
25
26
27 HELPLIST_S *help_list;
28
29
30 void preamble(FILE *ofp);
31 void body(FILE *ifp, FILE *ofp);
32 char *quote_clean(char *rawline);
33 int only_tags(char *line);
34 int append_to_help_list(HELPLIST_S **, char *new);
35 void print_help_list(HELPLIST_S *, FILE *fp);
36
37
38 int
main(int argc,char ** argv)39 main(int argc, char **argv)
40 {
41 preamble(stdout);
42 body(stdin, stdout);
43 exit(0);
44 }
45
46
47 void
preamble(FILE * ofp)48 preamble(FILE *ofp)
49 {
50 fprintf(ofp, "\n\t\t/*\n");
51 fprintf(ofp, "\t\t * AUTOMATICALLY GENERATED FILE!\n");
52 fprintf(ofp, "\t\t * DO NOT EDIT!!\n");
53 fprintf(ofp, "\t\t * See help_c_gen.c.\n\t\t */\n\n\n");
54 fprintf(ofp, "#include <stdio.h>\n#include \"headers.h\"\n#include \"helptext.h\"\n\n");
55 }
56
57
58 void
body(FILE * ifp,FILE * ofp)59 body(FILE *ifp, FILE *ofp)
60 {
61 char rawline[10000];
62 char *line;
63 #define SPACE ' '
64 char *p, *helpname;
65 int in_text = 0, new_topic = 0, first_one = 1, justtags;
66
67 while(fgets(rawline, sizeof(rawline), ifp) != NULL){
68 if(rawline[0] == '#')
69 continue;
70
71 line = quote_clean(rawline);
72
73 if(!line){
74 /*
75 * Put errors in result so that it will cause a compile
76 * error and be noticed.
77 */
78 fprintf(ofp, "Error: quote_clean returns NULL for help line\n %s\n", rawline);
79 exit(-1);
80 }
81
82 justtags = 0;
83 if(!strncmp(line, "====", 4)){
84 p = line;
85 /* skip to first space */
86 while(*p && *p != SPACE)
87 p++;
88
89 if(!*p){
90 fprintf(ofp, "Error: help input line\n %s\n No space after ====\n", rawline);
91 exit(-1);
92 }
93
94 /* skip spaces */
95 while(*p && *p == SPACE)
96 p++;
97
98 if(!*p){
99 fprintf(ofp, "Error: help input line\n %s\n Missing helpname after ====\n", rawline);
100 exit(-1);
101 }
102
103 helpname = p;
104
105 /* skip to next space */
106 while(*p && *p != SPACE)
107 p++;
108
109 *p = '\0'; /* tie off helpname */
110
111 /* finish previous one */
112 if(in_text)
113 fprintf(ofp, "NULL\n};\n\n\n");
114
115 in_text = new_topic = 1;
116
117 fprintf(ofp, "char *%s[] = {\n", helpname);
118
119 if(append_to_help_list(&help_list, helpname) < 0){
120 fprintf(ofp, "Error: Can't allocate memory for help_list after line\n %s\n", rawline);
121 exit(-1);
122 }
123 }
124 else if(line[0] == '\0'){
125 if(in_text)
126 fprintf(ofp, "\" \",\n"); /* why the space? */
127 }
128 else if(only_tags(line)){
129 if(in_text){
130 fprintf(ofp, "\"%s\",\n", line);
131 justtags = 1;
132 }
133 }
134
135 if(line[0] && line[0] != '='){
136 if(in_text && !justtags){
137 if(first_one){
138 first_one = 0;
139 fprintf(ofp, "/*\n");
140 fprintf(ofp, "TRANSLATORS: The translation strings for pith/helptext.c\n");
141 fprintf(ofp, "are automatically generated by a script from the help\n");
142 fprintf(ofp, "text in pith/pine.hlp. This means that the translation job for\n");
143 fprintf(ofp, "the help text is particularly difficult.\n");
144 fprintf(ofp, "This is HTML source so please leave the text inside HTML tags untranslated.\n");
145 fprintf(ofp, "HTML tags like <LI> or <TITLE> should, of course, be left untranslated.\n");
146 fprintf(ofp, "Special HTML characters like < (less than character) should be left alone.\n");
147 fprintf(ofp, "Alpine option names are short phrases with the words separated by\n");
148 fprintf(ofp, "dashes. An example of an option name is Quell-Extra-Post-Prompt.\n");
149 fprintf(ofp, "Option names should not be translated.\n");
150 fprintf(ofp, "The file pith/helptext.c contains many separate help topics.\n");
151 fprintf(ofp, "Some of them are very short and some are long. If left unsorted the\n");
152 fprintf(ofp, "text for a single topic is together in the translation file. The start\n");
153 fprintf(ofp, "of each new topic is marked by the comment\n");
154 fprintf(ofp, "TRANSLATORS: Start of new help topic.\n");
155 fprintf(ofp, "*/\n");
156 }
157 else if(new_topic){
158 new_topic = 0;
159 fprintf(ofp, "/* TRANSLATORS: Start of new help topic. */\n");
160 }
161
162 fprintf(ofp, "N_(\"%s\"),\n", line);
163 }
164 else{
165 ; /* skip leading cruft */
166 }
167 }
168 }
169
170 if(in_text)
171 fprintf(ofp, "NULL\n};\n\n\n");
172
173 print_help_list(help_list, ofp);
174 }
175
176
177 char *
quote_clean(char * rawline)178 quote_clean(char *rawline)
179 {
180 char *p, *q, *cleaned = NULL;
181 size_t len;
182
183 if(rawline){
184 len = strlen(rawline);
185 cleaned = (char *) malloc((2*len+1) * sizeof(char));
186
187 if(cleaned){
188 p = rawline;
189 q = cleaned;
190
191 while(*p && *p != '\n'){
192 if(*p == '"' && !(p > rawline && *(p-1) == '\\'))
193 *q++ = '\\';
194
195 *q++ = *p++;
196 }
197
198 *q = '\0';
199 }
200 }
201
202 return cleaned;
203 }
204
205
206 int
only_tags(char * line)207 only_tags(char *line)
208 {
209 char *p;
210 int is_tags = 1; /* only tags seen so far */
211
212 if(!line)
213 return 0;
214
215 p = line;
216
217 while(is_tags && *p){
218 /* leading space before a tag */
219 while(*p && isspace(*p))
220 p++;
221
222 if(*p == '<'){
223 p++;
224 /* skip through interior of tag */
225 while(*p && *p != '<' && *p != '>')
226 p++;
227
228 if(*p == '>'){
229 p++;
230 /* trailing space after tag */
231 while(*p && isspace(*p))
232 p++;
233 }
234 else
235 is_tags = 0;
236 }
237 else if(*p)
238 is_tags = 0;
239 }
240
241 return is_tags;
242 }
243
244
245 int
append_to_help_list(HELPLIST_S ** head,char * name)246 append_to_help_list(HELPLIST_S **head, char *name)
247 {
248 HELPLIST_S *new, *h;
249 size_t len;
250
251 if(!(name && *name && head))
252 return 0;
253
254 new = (HELPLIST_S *) malloc(sizeof(*new));
255 if(!new)
256 return -1;
257
258 memset(new, 0, sizeof(*new));
259 len = strlen(name);
260 new->name = (char *) malloc((len+1) * sizeof(char));
261 strncpy(new->name, name, len);
262 new->name[len] = '\0';
263
264 if(*head){
265 for(h = *head; h->next; h = h->next)
266 ;
267
268 h->next = new;
269 }
270 else
271 *head = new;
272
273 return 0;
274 }
275
276
277 void
print_help_list(HELPLIST_S * head,FILE * fp)278 print_help_list(HELPLIST_S *head, FILE *fp)
279 {
280 HELPLIST_S *h;
281
282 if(head){
283 fprintf(fp, "struct help_texts h_texts[] = {\n");
284
285 for(h = head; h; h = h->next)
286 if(h->name && h->name[0])
287 fprintf(fp, "{%s,\"%s\"},\n", h->name, h->name);
288
289 fprintf(fp, "{NO_HELP, NULL}\n};\n");
290 }
291 }
292