By Wincent Balin: Cleaned up unneeded prototypes in s_path.c (ongoing FS #10416)
[kugel-rb.git] / apps / plugins / pdbox / PDa / src / s_path.c
blob558d8bd9073e024ee369dfd39c9bfcd72f04be9a
1 /* Copyright (c) 1999 Guenter Geiger and others.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
5 /*
6 * This file implements the loader for linux, which includes
7 * a little bit of path handling.
9 * Generalized by MSP to provide an open_via_path function
10 * and lists of files for all purposes.
11 */
13 /* #define DEBUG(x) x */
14 #define DEBUG(x)
15 void readsf_banana( void); /* debugging */
17 #ifdef ROCKBOX
19 #include "plugin.h"
20 #include "pdbox.h"
22 #include "m_pd.h"
23 #include "m_imp.h"
24 #include "s_stuff.h"
26 #else /* ROCKBOX */
27 #include <stdlib.h>
28 #ifdef UNIX
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #endif
32 #ifdef MSW
33 #include <io.h>
34 #endif
36 #include <string.h>
37 #include "m_pd.h"
38 #include "m_imp.h"
39 #include "s_stuff.h"
40 #include <stdio.h>
41 #include <fcntl.h>
42 #endif /* ROCKBOX */
44 static t_namelist *pd_path, *pd_helppath;
46 /* Utility functions */
48 /* copy until delimiter and return position after delimiter in string */
49 /* if it was the last substring, return NULL */
51 static const char* strtokcpy(char *to, const char *from, int delim)
53 int size = 0;
55 while (from[size] != (char)delim && from[size] != '\0')
56 size++;
58 strncpy(to,from,size);
59 to[size] = '\0';
60 if (from[size] == '\0') return NULL;
61 if (size) return from+size+1;
62 else return NULL;
65 /* add a colon-separated list of names to a namelist */
67 #ifdef MSW
68 #define SEPARATOR ';'
69 #else
70 #define SEPARATOR ':'
71 #endif
73 static t_namelist *namelist_doappend(t_namelist *listwas, const char *s)
75 t_namelist *nl = listwas, *rtn = listwas, *nl2;
76 nl2 = (t_namelist *)(getbytes(sizeof(*nl)));
77 nl2->nl_next = 0;
78 nl2->nl_string = (char *)getbytes(strlen(s) + 1);
79 strcpy(nl2->nl_string, s);
80 sys_unbashfilename(nl2->nl_string, nl2->nl_string);
81 if (!nl)
82 nl = rtn = nl2;
83 else
85 while (nl->nl_next)
86 nl = nl->nl_next;
87 nl->nl_next = nl2;
89 return (rtn);
93 t_namelist *namelist_append(t_namelist *listwas, const char *s)
95 const char *npos;
96 char temp[MAXPDSTRING];
97 t_namelist *nl = listwas, *rtn = listwas;
99 #ifdef ROCKBOX
100 (void) rtn;
101 #endif
103 npos = s;
106 npos = strtokcpy(temp, npos, SEPARATOR);
107 if (! *temp) continue;
108 nl = namelist_doappend(nl, temp);
110 while (npos);
111 return (nl);
114 void namelist_free(t_namelist *listwas)
116 t_namelist *nl, *nl2;
117 for (nl = listwas; nl; nl = nl2)
119 nl2 = nl->nl_next;
120 t_freebytes(nl->nl_string, strlen(nl->nl_string) + 1);
121 t_freebytes(nl, sizeof(*nl));
125 void sys_addpath(const char *p)
127 pd_path = namelist_append(pd_path, p);
130 void sys_addhelppath(const char *p)
132 pd_helppath = namelist_append(pd_helppath, p);
135 #ifdef MSW
136 #define MSWOPENFLAG(bin) (bin ? _O_BINARY : _O_TEXT)
137 #else
138 #define MSWOPENFLAG(bin) 0
139 #endif
141 /* search for a file in a specified directory, then along the globally
142 defined search path, using ext as filename extension. Exception:
143 if the 'name' starts with a slash or a letter, colon, and slash in MSW,
144 there is no search and instead we just try to open the file literally. The
145 fd is returned, the directory ends up in the "dirresult" which must be at
146 least "size" bytes. "nameresult" is set to point to the filename, which
147 ends up in the same buffer as dirresult. */
149 int open_via_path(const char *dir, const char *name, const char* ext,
150 char *dirresult, char **nameresult, unsigned int size, int bin)
152 t_namelist *nl, thislist;
153 int fd = -1;
154 char listbuf[MAXPDSTRING];
156 #ifdef ROCKBOX
157 (void) bin;
158 #endif
160 if (name[0] == '/'
161 #ifdef MSW
162 || (name[1] == ':' && name[2] == '/')
163 #endif
166 thislist.nl_next = 0;
167 thislist.nl_string = listbuf;
168 listbuf[0] = 0;
170 else
172 thislist.nl_string = listbuf;
173 thislist.nl_next = pd_path;
174 strncpy(listbuf, dir, MAXPDSTRING);
175 listbuf[MAXPDSTRING-1] = 0;
176 sys_unbashfilename(listbuf, listbuf);
179 for (nl = &thislist; nl; nl = nl->nl_next)
181 if (strlen(nl->nl_string) + strlen(name) + strlen(ext) + 4 >
182 size)
183 continue;
184 strcpy(dirresult, nl->nl_string);
185 if (*dirresult && dirresult[strlen(dirresult)-1] != '/')
186 strcat(dirresult, "/");
187 strcat(dirresult, name);
188 strcat(dirresult, ext);
189 sys_bashfilename(dirresult, dirresult);
191 DEBUG(post("looking for %s",dirresult));
192 /* see if we can open the file for reading */
193 if ((fd=open(dirresult,O_RDONLY | MSWOPENFLAG(bin))) >= 0)
195 /* in UNIX, further check that it's not a directory */
196 #ifdef UNIX
197 struct stat statbuf;
198 int ok = ((fstat(fd, &statbuf) >= 0) &&
199 !S_ISDIR(statbuf.st_mode));
200 if (!ok)
202 if (sys_verbose) post("tried %s; stat failed or directory",
203 dirresult);
204 close (fd);
205 fd = -1;
207 else
208 #endif
210 char *slash;
211 if (sys_verbose) post("tried %s and succeeded", dirresult);
212 sys_unbashfilename(dirresult, dirresult);
214 slash = strrchr(dirresult, '/');
215 if (slash)
217 *slash = 0;
218 *nameresult = slash + 1;
220 else *nameresult = dirresult;
222 return (fd);
225 else
227 if (sys_verbose) post("tried %s and failed", dirresult);
230 *dirresult = 0;
231 *nameresult = dirresult;
232 return (-1);
235 static int do_open_via_helppath(const char *realname, t_namelist *listp)
237 t_namelist *nl;
238 int fd = -1;
239 char dirresult[MAXPDSTRING], realdir[MAXPDSTRING];
240 for (nl = listp; nl; nl = nl->nl_next)
242 strcpy(dirresult, nl->nl_string);
243 strcpy(realdir, dirresult);
244 if (*dirresult && dirresult[strlen(dirresult)-1] != '/')
245 strcat(dirresult, "/");
246 strcat(dirresult, realname);
247 sys_bashfilename(dirresult, dirresult);
249 DEBUG(post("looking for %s",dirresult));
250 /* see if we can open the file for reading */
251 if ((fd=open(dirresult,O_RDONLY | MSWOPENFLAG(0))) >= 0)
253 /* in UNIX, further check that it's not a directory */
254 #ifdef UNIX
255 struct stat statbuf;
256 int ok = ((fstat(fd, &statbuf) >= 0) &&
257 !S_ISDIR(statbuf.st_mode));
258 if (!ok)
260 if (sys_verbose) post("tried %s; stat failed or directory",
261 dirresult);
262 close (fd);
263 fd = -1;
265 else
266 #endif
268 #ifndef ROCKBOX
269 char *slash;
270 #endif
271 if (sys_verbose) post("tried %s and succeeded", dirresult);
272 sys_unbashfilename(dirresult, dirresult);
273 close (fd);
274 glob_evalfile(0, gensym((char*)realname), gensym(realdir));
275 return (1);
278 else
280 if (sys_verbose) post("tried %s and failed", dirresult);
283 return (0);
286 /* LATER make this use open_via_path above. We expect the ".pd"
287 suffix here, even though we have to tear it back off for one of the
288 search attempts. */
289 void open_via_helppath(const char *name, const char *dir)
291 #ifdef ROCKBOX
292 t_namelist thislist, *listp;
293 #else /*ROCKBOX */
294 t_namelist *nl, thislist, *listp;
295 int fd = -1;
296 #endif /* ROCKBOX */
297 char dirbuf2[MAXPDSTRING], realname[MAXPDSTRING];
299 /* if directory is supplied, put it at head of search list. */
300 if (*dir)
302 thislist.nl_string = dirbuf2;
303 thislist.nl_next = pd_helppath;
304 strncpy(dirbuf2, dir, MAXPDSTRING);
305 dirbuf2[MAXPDSTRING-1] = 0;
306 sys_unbashfilename(dirbuf2, dirbuf2);
307 listp = &thislist;
309 else listp = pd_helppath;
310 /* 1. "objectname-help.pd" */
311 strncpy(realname, name, MAXPDSTRING-10);
312 realname[MAXPDSTRING-10] = 0;
313 if (strlen(realname) > 3 && !strcmp(realname+strlen(realname)-3, ".pd"))
314 realname[strlen(realname)-3] = 0;
315 strcat(realname, "-help.pd");
316 if (do_open_via_helppath(realname, listp))
317 return;
318 /* 2. "help-objectname.pd" */
319 strcpy(realname, "help-");
320 strncat(realname, name, MAXPDSTRING-10);
321 realname[MAXPDSTRING-1] = 0;
322 if (do_open_via_helppath(realname, listp))
323 return;
324 /* 3. "objectname.pd" */
325 if (do_open_via_helppath(name, listp))
326 return;
327 post("sorry, couldn't find help patch for \"%s\"", name);
328 return;
332 /* Startup file reading for linux and MACOSX. This should be replaced by
333 a better mechanism. This should be integrated with the audio, MIDI, and
334 path dialog system. */
336 #ifdef UNIX
338 #define STARTUPNAME ".pdrc"
339 #define NUMARGS 1000
341 int sys_argparse(int argc, char **argv);
343 int sys_rcfile(void)
345 FILE* file;
346 int i;
347 int k;
348 int rcargc;
349 char* rcargv[NUMARGS];
350 char* buffer;
351 char fname[MAXPDSTRING], buf[1000], *home = getenv("HOME");
353 /* parse a startup file */
355 *fname = '\0';
357 strncat(fname, home? home : ".", MAXPDSTRING-10);
358 strcat(fname, "/");
360 strcat(fname, STARTUPNAME);
362 if (!(file = fopen(fname, "r")))
363 return 1;
365 post("reading startup file: %s", fname);
367 rcargv[0] = "."; /* this no longer matters to sys_argparse() */
369 for (i = 1; i < NUMARGS-1; i++)
371 if (fscanf(file, "%999s", buf) < 0)
372 break;
373 buf[1000] = 0;
374 if (!(rcargv[i] = malloc(strlen(buf) + 1)))
375 return (1);
376 strcpy(rcargv[i], buf);
378 if (i >= NUMARGS-1)
379 fprintf(stderr, "startup file too long; extra args dropped\n");
380 rcargv[i] = 0;
382 rcargc = i;
384 /* parse the options */
386 fclose(file);
387 if (sys_verbose)
389 if (rcargv)
391 post("startup args from RC file:");
392 for (i = 1; i < rcargc; i++)
393 post("%s", rcargv[i]);
395 else post("no RC file arguments found");
397 if (sys_argparse(rcargc, rcargv))
399 post("error parsing RC arguments");
400 return (1);
402 return (0);
404 #endif /* UNIX */
406 /* start an audio settings dialog window */
407 void glob_start_path_dialog(t_pd *dummy, t_floatarg flongform)
409 #ifdef ROCKBOX
410 (void) dummy;
411 (void) flongform;
412 #else /* ROCKBOX */
413 char buf[MAXPDSTRING];
414 int i;
415 t_namelist *nl;
417 for (nl = pd_path, i = 0; nl && i < 10; nl = nl->nl_next, i++)
418 sys_vgui("pd_set pd_path%d \"%s\"\n", i, nl->nl_string);
419 for (; i < 10; i++)
420 sys_vgui("pd_set pd_path%d \"\"\n", i);
422 sprintf(buf, "pdtk_path_dialog %%s\n");
423 gfxstub_new(&glob_pdobject, glob_start_path_dialog, buf);
424 #endif /* ROCKBOX */
427 /* new values from dialog window */
428 void glob_path_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
430 int i;
432 #ifdef ROCKBOX
433 (void) dummy;
434 (void) s;
435 #endif /* ROCKBOX */
437 namelist_free(pd_path);
438 pd_path = 0;
439 for (i = 0; i < argc; i++)
441 t_symbol *s = atom_getsymbolarg(i, argc, argv);
442 if (*s->s_name)
443 sys_addpath(s->s_name);