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