1 /* GENIUS Calculator
2 * Copyright (C) 1997-2016 Jiri (George) Lebl
3 *
4 * Author: Jiri (George) Lebl
5 *
6 * This file is part of Genius.
7 *
8 * Genius is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <dirent.h>
25 #include <unistd.h>
26 #include <signal.h>
27 #include <glob.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <math.h>
31 #include <time.h>
32 #include <glib.h>
33 #include <gmodule.h>
34 #include <readline/readline.h>
35 #include <readline/history.h>
36 #include <readline/tilde.h>
37
38 #include <vicious.h>
39
40 #include "calc.h"
41 #include "eval.h"
42 #include "util.h"
43 #include "dict.h"
44 #include "compil.h"
45
46 #include "mpwrap.h"
47
48 #include "parse.h"
49
50 #include "examples.h"
51
52 #include "binreloc.h"
53
54 GSList *gel_example_list = NULL;
55 GSList *gel_example_categories_list = NULL;
56
57
58 static GelExampleCategory *
gel_get_example_category(const char * name)59 gel_get_example_category (const char *name)
60 {
61 GSList *li;
62 static GelExampleCategory *last = NULL;
63 GelExampleCategory *cat;
64
65 if (last != NULL && strcmp(last->name, name) == 0) {
66 return last;
67 }
68
69 for (li = gel_example_categories_list; li != NULL; li = li->next) {
70 cat = li->data;
71 if (strcmp (cat->name, name) == 0) {
72 last = cat;
73 return cat;
74 }
75 }
76
77 cat = g_new (GelExampleCategory, 1);
78 cat->name = g_strdup (name);
79 cat->examples = NULL;
80
81 gel_example_categories_list =
82 g_slist_prepend (gel_example_categories_list, cat);
83
84 last = cat;
85
86 return cat;
87 }
88
89 static GelExample *
gel_readexample(const char * dir_name,const char * file_name)90 gel_readexample (const char *dir_name, const char *file_name)
91 {
92 char *f = g_build_filename (ve_sure_string (dir_name),
93 ve_sure_string (file_name), NULL);
94 FILE *fp;
95 char buf[512];
96 char *name;
97 char *cat;
98 char *s;
99 GelExample *exam = NULL;
100
101 fp = fopen (f, "r");
102
103 if (fp == NULL) {
104 g_free (f);
105 return NULL;
106 }
107
108 if (fgets (buf, sizeof (buf), fp) == NULL) {
109 g_free (f);
110 fclose (fp);
111 return NULL;
112 }
113
114 s = strchr (buf, ':');
115 if (s != NULL) {
116 cat = g_strdup (g_strstrip(s+1));
117 } else {
118 g_free (f);
119 fclose (fp);
120 return NULL;
121 }
122
123 if (fgets (buf, sizeof (buf), fp) == NULL) {
124 g_free (f);
125 g_free (cat);
126 fclose (fp);
127 return NULL;
128 }
129
130 s = strchr (buf, ':');
131 if (s != NULL) {
132 name = g_strdup (g_strstrip (s+1));
133 } else {
134 g_free (f);
135 g_free (cat);
136 fclose (fp);
137 return NULL;
138 }
139
140 fclose (fp);
141
142 exam = g_new (GelExample, 1);
143 exam->category = cat;
144 exam->name = name;
145 exam->file = f;
146
147 return exam;
148 }
149
150 static void
read_examples_from_dir(const char * dir_name)151 read_examples_from_dir (const char *dir_name)
152 {
153 DIR *dir;
154 struct dirent *dent;
155
156 dir = opendir (dir_name);
157 if (dir == NULL) {
158 return;
159 }
160 while((dent = readdir (dir)) != NULL) {
161 char *p;
162 GelExample *exam;
163 if(dent->d_name[0] == '.' &&
164 (dent->d_name[1] == '\0' ||
165 (dent->d_name[1] == '.' &&
166 dent->d_name[2] == '\0')))
167 continue;
168 p = strrchr(dent->d_name,'.');
169 if(!p || strcmp(p,".gel")!=0)
170 continue;
171 exam = gel_readexample (dir_name, dent->d_name);
172 if (exam != NULL) {
173 GelExampleCategory *cat;
174
175 gel_example_list = g_slist_prepend (gel_example_list,
176 exam);
177 cat = gel_get_example_category (exam->category);
178 cat->examples = g_slist_prepend (cat->examples, exam);
179 }
180 }
181 closedir (dir);
182 }
183
184 static int
compare_examples(GelExample * a,GelExample * b)185 compare_examples (GelExample *a, GelExample *b)
186 {
187 int s = strcmp (a->category, b->category);
188 if (s != 0)
189 return s;
190 return strcmp (a->name, b->name);
191 }
192
193 static int
compare_examples_byname(GelExample * a,GelExample * b)194 compare_examples_byname (GelExample *a, GelExample *b)
195 {
196 return strcmp (a->name, b->name);
197 }
198
199 static int
compare_example_categories(GelExampleCategory * a,GelExampleCategory * b)200 compare_example_categories (GelExampleCategory *a, GelExampleCategory *b)
201 {
202 return strcmp (a->name, b->name);
203 }
204
205 void
gel_read_example_list(void)206 gel_read_example_list (void)
207 {
208 GSList *li;
209 char *dir_name;
210 char *datadir;
211
212 datadir = gbr_find_data_dir (DATADIR);
213 dir_name = g_build_filename (datadir, "genius", "examples", NULL);
214 g_free (datadir);
215 read_examples_from_dir (dir_name);
216 g_free (dir_name);
217
218 dir_name = g_build_filename (g_get_home_dir (),
219 ".genius", "examples", NULL);
220 read_examples_from_dir (dir_name);
221 g_free (dir_name);
222
223 gel_example_list = g_slist_sort (gel_example_list,
224 (GCompareFunc)compare_examples);
225
226 gel_example_categories_list =
227 g_slist_sort (gel_example_categories_list,
228 (GCompareFunc)compare_example_categories);
229
230 for (li = gel_example_categories_list; li != NULL; li = li->next) {
231 GelExampleCategory *cat = li->data;
232 cat->examples =
233 g_slist_sort (cat->examples,
234 (GCompareFunc)compare_examples_byname);
235 }
236 }
237