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. */
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.
13 /* #define DEBUG(x) x */
15 void readsf_banana( void); /* debugging */
33 static t_namelist
*pd_path
, *pd_helppath
;
35 /* Utility functions */
37 /* copy until delimiter and return position after delimiter in string */
38 /* if it was the last substring, return NULL */
40 static const char* strtokcpy(char *to
, const char *from
, int delim
)
44 while (from
[size
] != (char)delim
&& from
[size
] != '\0')
47 strncpy(to
,from
,size
);
49 if (from
[size
] == '\0') return NULL
;
50 if (size
) return from
+size
+1;
54 /* add a colon-separated list of names to a namelist */
62 static t_namelist
*namelist_doappend(t_namelist
*listwas
, const char *s
)
64 t_namelist
*nl
= listwas
, *rtn
= listwas
, *nl2
;
65 nl2
= (t_namelist
*)(getbytes(sizeof(*nl
)));
67 nl2
->nl_string
= (char *)getbytes(strlen(s
) + 1);
68 strcpy(nl2
->nl_string
, s
);
69 sys_unbashfilename(nl2
->nl_string
, nl2
->nl_string
);
82 t_namelist
*namelist_append(t_namelist
*listwas
, const char *s
)
85 char temp
[MAXPDSTRING
];
86 t_namelist
*nl
= listwas
, *rtn
= listwas
;
91 npos
= strtokcpy(temp
, npos
, SEPARATOR
);
92 if (! *temp
) continue;
93 nl
= namelist_doappend(nl
, temp
);
99 void namelist_free(t_namelist
*listwas
)
101 t_namelist
*nl
, *nl2
;
102 for (nl
= listwas
; nl
; nl
= nl2
)
105 t_freebytes(nl
->nl_string
, strlen(nl
->nl_string
) + 1);
106 t_freebytes(nl
, sizeof(*nl
));
110 void sys_addpath(const char *p
)
112 pd_path
= namelist_append(pd_path
, p
);
115 void sys_addhelppath(const char *p
)
117 pd_helppath
= namelist_append(pd_helppath
, p
);
121 #define MSWOPENFLAG(bin) (bin ? _O_BINARY : _O_TEXT)
123 #define MSWOPENFLAG(bin) 0
126 /* search for a file in a specified directory, then along the globally
127 defined search path, using ext as filename extension. Exception:
128 if the 'name' starts with a slash or a letter, colon, and slash in MSW,
129 there is no search and instead we just try to open the file literally. The
130 fd is returned, the directory ends up in the "dirresult" which must be at
131 least "size" bytes. "nameresult" is set to point to the filename, which
132 ends up in the same buffer as dirresult. */
134 int open_via_path(const char *dir
, const char *name
, const char* ext
,
135 char *dirresult
, char **nameresult
, unsigned int size
, int bin
)
137 t_namelist
*nl
, thislist
;
139 char listbuf
[MAXPDSTRING
];
143 || (name
[1] == ':' && name
[2] == '/')
147 thislist
.nl_next
= 0;
148 thislist
.nl_string
= listbuf
;
153 thislist
.nl_string
= listbuf
;
154 thislist
.nl_next
= pd_path
;
155 strncpy(listbuf
, dir
, MAXPDSTRING
);
156 listbuf
[MAXPDSTRING
-1] = 0;
157 sys_unbashfilename(listbuf
, listbuf
);
160 for (nl
= &thislist
; nl
; nl
= nl
->nl_next
)
162 if (strlen(nl
->nl_string
) + strlen(name
) + strlen(ext
) + 4 >
165 strcpy(dirresult
, nl
->nl_string
);
166 if (*dirresult
&& dirresult
[strlen(dirresult
)-1] != '/')
167 strcat(dirresult
, "/");
168 strcat(dirresult
, name
);
169 strcat(dirresult
, ext
);
170 sys_bashfilename(dirresult
, dirresult
);
172 DEBUG(post("looking for %s",dirresult
));
173 /* see if we can open the file for reading */
174 if ((fd
=open(dirresult
,O_RDONLY
| MSWOPENFLAG(bin
))) >= 0)
176 /* in UNIX, further check that it's not a directory */
179 int ok
= ((fstat(fd
, &statbuf
) >= 0) &&
180 !S_ISDIR(statbuf
.st_mode
));
183 if (sys_verbose
) post("tried %s; stat failed or directory",
192 if (sys_verbose
) post("tried %s and succeeded", dirresult
);
193 sys_unbashfilename(dirresult
, dirresult
);
194 slash
= strrchr(dirresult
, '/');
198 *nameresult
= slash
+ 1;
200 else *nameresult
= dirresult
;
207 if (sys_verbose
) post("tried %s and failed", dirresult
);
211 *nameresult
= dirresult
;
215 static int do_open_via_helppath(const char *realname
, t_namelist
*listp
)
219 char dirresult
[MAXPDSTRING
], realdir
[MAXPDSTRING
];
220 for (nl
= listp
; nl
; nl
= nl
->nl_next
)
222 strcpy(dirresult
, nl
->nl_string
);
223 strcpy(realdir
, dirresult
);
224 if (*dirresult
&& dirresult
[strlen(dirresult
)-1] != '/')
225 strcat(dirresult
, "/");
226 strcat(dirresult
, realname
);
227 sys_bashfilename(dirresult
, dirresult
);
229 DEBUG(post("looking for %s",dirresult
));
230 /* see if we can open the file for reading */
231 if ((fd
=open(dirresult
,O_RDONLY
| MSWOPENFLAG(0))) >= 0)
233 /* in UNIX, further check that it's not a directory */
236 int ok
= ((fstat(fd
, &statbuf
) >= 0) &&
237 !S_ISDIR(statbuf
.st_mode
));
240 if (sys_verbose
) post("tried %s; stat failed or directory",
249 if (sys_verbose
) post("tried %s and succeeded", dirresult
);
250 sys_unbashfilename(dirresult
, dirresult
);
252 glob_evalfile(0, gensym((char*)realname
), gensym(realdir
));
258 if (sys_verbose
) post("tried %s and failed", dirresult
);
264 /* LATER make this use open_via_path above. We expect the ".pd"
265 suffix here, even though we have to tear it back off for one of the
267 void open_via_helppath(const char *name
, const char *dir
)
269 t_namelist
*nl
, thislist
, *listp
;
271 char dirbuf2
[MAXPDSTRING
], realname
[MAXPDSTRING
];
273 /* if directory is supplied, put it at head of search list. */
276 thislist
.nl_string
= dirbuf2
;
277 thislist
.nl_next
= pd_helppath
;
278 strncpy(dirbuf2
, dir
, MAXPDSTRING
);
279 dirbuf2
[MAXPDSTRING
-1] = 0;
280 sys_unbashfilename(dirbuf2
, dirbuf2
);
283 else listp
= pd_helppath
;
284 /* 1. "objectname-help.pd" */
285 strncpy(realname
, name
, MAXPDSTRING
-10);
286 realname
[MAXPDSTRING
-10] = 0;
287 if (strlen(realname
) > 3 && !strcmp(realname
+strlen(realname
)-3, ".pd"))
288 realname
[strlen(realname
)-3] = 0;
289 strcat(realname
, "-help.pd");
290 if (do_open_via_helppath(realname
, listp
))
292 /* 2. "help-objectname.pd" */
293 strcpy(realname
, "help-");
294 strncat(realname
, name
, MAXPDSTRING
-10);
295 realname
[MAXPDSTRING
-1] = 0;
296 if (do_open_via_helppath(realname
, listp
))
298 /* 3. "objectname.pd" */
299 if (do_open_via_helppath(name
, listp
))
301 post("sorry, couldn't find help patch for \"%s\"", name
);
306 /* Startup file reading for linux and MACOSX. This should be replaced by
307 a better mechanism. This should be integrated with the audio, MIDI, and
308 path dialog system. */
312 #define STARTUPNAME ".pdrc"
315 int sys_argparse(int argc
, char **argv
);
323 char* rcargv
[NUMARGS
];
325 char fname
[MAXPDSTRING
], buf
[1000], *home
= getenv("HOME");
327 /* parse a startup file */
331 strncat(fname
, home
? home
: ".", MAXPDSTRING
-10);
334 strcat(fname
, STARTUPNAME
);
336 if (!(file
= fopen(fname
, "r")))
339 post("reading startup file: %s", fname
);
341 rcargv
[0] = "."; /* this no longer matters to sys_argparse() */
343 for (i
= 1; i
< NUMARGS
-1; i
++)
345 if (fscanf(file
, "%999s", buf
) < 0)
348 if (!(rcargv
[i
] = malloc(strlen(buf
) + 1)))
350 strcpy(rcargv
[i
], buf
);
353 fprintf(stderr
, "startup file too long; extra args dropped\n");
358 /* parse the options */
365 post("startup args from RC file:");
366 for (i
= 1; i
< rcargc
; i
++)
367 post("%s", rcargv
[i
]);
369 else post("no RC file arguments found");
371 if (sys_argparse(rcargc
, rcargv
))
373 post("error parsing RC arguments");
380 /* start an audio settings dialog window */
381 void glob_start_path_dialog(t_pd
*dummy
, t_floatarg flongform
)
383 char buf
[MAXPDSTRING
];
387 for (nl
= pd_path
, i
= 0; nl
&& i
< 10; nl
= nl
->nl_next
, i
++)
388 sys_vgui("pd_set pd_path%d \"%s\"\n", i
, nl
->nl_string
);
390 sys_vgui("pd_set pd_path%d \"\"\n", i
);
392 sprintf(buf
, "pdtk_path_dialog %%s\n");
393 gfxstub_new(&glob_pdobject
, glob_start_path_dialog
, buf
);
396 /* new values from dialog window */
397 void glob_path_dialog(t_pd
*dummy
, t_symbol
*s
, int argc
, t_atom
*argv
)
400 namelist_free(pd_path
);
402 for (i
= 0; i
< argc
; i
++)
404 t_symbol
*s
= atom_getsymbolarg(i
, argc
, argv
);
406 sys_addpath(s
->s_name
);
411 /* Copyright (c) 1999 Guenter Geiger and others.
412 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
413 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
416 * This file implements the loader for linux, which includes
417 * a little bit of path handling.
419 * Generalized by MSP to provide an open_via_path function
420 * and lists of files for all purposes.
423 /* #define DEBUG(x) x */
425 void readsf_banana( void); /* debugging */
430 #include <sys/stat.h>
443 static t_namelist
*pd_path
, *pd_helppath
;
445 /* Utility functions */
447 /* copy until delimiter and return position after delimiter in string */
448 /* if it was the last substring, return NULL */
450 static const char* strtokcpy(char *to
, const char *from
, int delim
)
454 while (from
[size
] != (char)delim
&& from
[size
] != '\0')
457 strncpy(to
,from
,size
);
459 if (from
[size
] == '\0') return NULL
;
460 if (size
) return from
+size
+1;
464 /* add a colon-separated list of names to a namelist */
467 #define SEPARATOR ';'
469 #define SEPARATOR ':'
472 static t_namelist
*namelist_doappend(t_namelist
*listwas
, const char *s
)
474 t_namelist
*nl
= listwas
, *rtn
= listwas
, *nl2
;
475 nl2
= (t_namelist
*)(getbytes(sizeof(*nl
)));
477 nl2
->nl_string
= (char *)getbytes(strlen(s
) + 1);
478 strcpy(nl2
->nl_string
, s
);
479 sys_unbashfilename(nl2
->nl_string
, nl2
->nl_string
);
492 t_namelist
*namelist_append(t_namelist
*listwas
, const char *s
)
495 char temp
[MAXPDSTRING
];
496 t_namelist
*nl
= listwas
, *rtn
= listwas
;
501 npos
= strtokcpy(temp
, npos
, SEPARATOR
);
502 if (! *temp
) continue;
503 nl
= namelist_doappend(nl
, temp
);
509 void namelist_free(t_namelist
*listwas
)
511 t_namelist
*nl
, *nl2
;
512 for (nl
= listwas
; nl
; nl
= nl2
)
515 t_freebytes(nl
->nl_string
, strlen(nl
->nl_string
) + 1);
516 t_freebytes(nl
, sizeof(*nl
));
520 void sys_addpath(const char *p
)
522 pd_path
= namelist_append(pd_path
, p
);
525 void sys_addhelppath(const char *p
)
527 pd_helppath
= namelist_append(pd_helppath
, p
);
531 #define MSWOPENFLAG(bin) (bin ? _O_BINARY : _O_TEXT)
533 #define MSWOPENFLAG(bin) 0
536 /* search for a file in a specified directory, then along the globally
537 defined search path, using ext as filename extension. Exception:
538 if the 'name' starts with a slash or a letter, colon, and slash in MSW,
539 there is no search and instead we just try to open the file literally. The
540 fd is returned, the directory ends up in the "dirresult" which must be at
541 least "size" bytes. "nameresult" is set to point to the filename, which
542 ends up in the same buffer as dirresult. */
544 int open_via_path(const char *dir
, const char *name
, const char* ext
,
545 char *dirresult
, char **nameresult
, unsigned int size
, int bin
)
547 t_namelist
*nl
, thislist
;
549 char listbuf
[MAXPDSTRING
];
553 || (name
[1] == ':' && name
[2] == '/')
557 thislist
.nl_next
= 0;
558 thislist
.nl_string
= listbuf
;
563 thislist
.nl_string
= listbuf
;
564 thislist
.nl_next
= pd_path
;
565 strncpy(listbuf
, dir
, MAXPDSTRING
);
566 listbuf
[MAXPDSTRING
-1] = 0;
567 sys_unbashfilename(listbuf
, listbuf
);
570 for (nl
= &thislist
; nl
; nl
= nl
->nl_next
)
572 if (strlen(nl
->nl_string
) + strlen(name
) + strlen(ext
) + 4 >
575 strcpy(dirresult
, nl
->nl_string
);
576 if (*dirresult
&& dirresult
[strlen(dirresult
)-1] != '/')
577 strcat(dirresult
, "/");
578 strcat(dirresult
, name
);
579 strcat(dirresult
, ext
);
580 sys_bashfilename(dirresult
, dirresult
);
582 DEBUG(post("looking for %s",dirresult
));
583 /* see if we can open the file for reading */
584 if ((fd
=open(dirresult
,O_RDONLY
| MSWOPENFLAG(bin
))) >= 0)
586 /* in UNIX, further check that it's not a directory */
589 int ok
= ((fstat(fd
, &statbuf
) >= 0) &&
590 !S_ISDIR(statbuf
.st_mode
));
593 if (sys_verbose
) post("tried %s; stat failed or directory",
602 if (sys_verbose
) post("tried %s and succeeded", dirresult
);
603 sys_unbashfilename(dirresult
, dirresult
);
604 slash
= strrchr(dirresult
, '/');
608 *nameresult
= slash
+ 1;
610 else *nameresult
= dirresult
;
617 if (sys_verbose
) post("tried %s and failed", dirresult
);
621 *nameresult
= dirresult
;
625 static int do_open_via_helppath(const char *realname
, t_namelist
*listp
)
629 char dirresult
[MAXPDSTRING
], realdir
[MAXPDSTRING
];
630 for (nl
= listp
; nl
; nl
= nl
->nl_next
)
632 strcpy(dirresult
, nl
->nl_string
);
633 strcpy(realdir
, dirresult
);
634 if (*dirresult
&& dirresult
[strlen(dirresult
)-1] != '/')
635 strcat(dirresult
, "/");
636 strcat(dirresult
, realname
);
637 sys_bashfilename(dirresult
, dirresult
);
639 DEBUG(post("looking for %s",dirresult
));
640 /* see if we can open the file for reading */
641 if ((fd
=open(dirresult
,O_RDONLY
| MSWOPENFLAG(0))) >= 0)
643 /* in UNIX, further check that it's not a directory */
646 int ok
= ((fstat(fd
, &statbuf
) >= 0) &&
647 !S_ISDIR(statbuf
.st_mode
));
650 if (sys_verbose
) post("tried %s; stat failed or directory",
659 if (sys_verbose
) post("tried %s and succeeded", dirresult
);
660 sys_unbashfilename(dirresult
, dirresult
);
662 glob_evalfile(0, gensym((char*)realname
), gensym(realdir
));
668 if (sys_verbose
) post("tried %s and failed", dirresult
);
674 /* LATER make this use open_via_path above. We expect the ".pd"
675 suffix here, even though we have to tear it back off for one of the
677 void open_via_helppath(const char *name
, const char *dir
)
679 t_namelist
*nl
, thislist
, *listp
;
681 char dirbuf2
[MAXPDSTRING
], realname
[MAXPDSTRING
];
683 /* if directory is supplied, put it at head of search list. */
686 thislist
.nl_string
= dirbuf2
;
687 thislist
.nl_next
= pd_helppath
;
688 strncpy(dirbuf2
, dir
, MAXPDSTRING
);
689 dirbuf2
[MAXPDSTRING
-1] = 0;
690 sys_unbashfilename(dirbuf2
, dirbuf2
);
693 else listp
= pd_helppath
;
694 /* 1. "objectname-help.pd" */
695 strncpy(realname
, name
, MAXPDSTRING
-10);
696 realname
[MAXPDSTRING
-10] = 0;
697 if (strlen(realname
) > 3 && !strcmp(realname
+strlen(realname
)-3, ".pd"))
698 realname
[strlen(realname
)-3] = 0;
699 strcat(realname
, "-help.pd");
700 if (do_open_via_helppath(realname
, listp
))
702 /* 2. "help-objectname.pd" */
703 strcpy(realname
, "help-");
704 strncat(realname
, name
, MAXPDSTRING
-10);
705 realname
[MAXPDSTRING
-1] = 0;
706 if (do_open_via_helppath(realname
, listp
))
708 /* 3. "objectname.pd" */
709 if (do_open_via_helppath(name
, listp
))
711 post("sorry, couldn't find help patch for \"%s\"", name
);
716 /* Startup file reading for linux and MACOSX. This should be replaced by
717 a better mechanism. This should be integrated with the audio, MIDI, and
718 path dialog system. */
722 #define STARTUPNAME ".pdrc"
725 int sys_argparse(int argc
, char **argv
);
733 char* rcargv
[NUMARGS
];
735 char fname
[MAXPDSTRING
], buf
[1000], *home
= getenv("HOME");
737 /* parse a startup file */
741 strncat(fname
, home
? home
: ".", MAXPDSTRING
-10);
744 strcat(fname
, STARTUPNAME
);
746 if (!(file
= fopen(fname
, "r")))
749 post("reading startup file: %s", fname
);
751 rcargv
[0] = "."; /* this no longer matters to sys_argparse() */
753 for (i
= 1; i
< NUMARGS
-1; i
++)
755 if (fscanf(file
, "%999s", buf
) < 0)
758 if (!(rcargv
[i
] = malloc(strlen(buf
) + 1)))
760 strcpy(rcargv
[i
], buf
);
763 fprintf(stderr
, "startup file too long; extra args dropped\n");
768 /* parse the options */
775 post("startup args from RC file:");
776 for (i
= 1; i
< rcargc
; i
++)
777 post("%s", rcargv
[i
]);
779 else post("no RC file arguments found");
781 if (sys_argparse(rcargc
, rcargv
))
783 post("error parsing RC arguments");
790 /* start an audio settings dialog window */
791 void glob_start_path_dialog(t_pd
*dummy
, t_floatarg flongform
)
793 char buf
[MAXPDSTRING
];
797 for (nl
= pd_path
, i
= 0; nl
&& i
< 10; nl
= nl
->nl_next
, i
++)
798 sys_vgui("pd_set pd_path%d \"%s\"\n", i
, nl
->nl_string
);
800 sys_vgui("pd_set pd_path%d \"\"\n", i
);
802 sprintf(buf
, "pdtk_path_dialog %%s\n");
803 gfxstub_new(&glob_pdobject
, glob_start_path_dialog
, buf
);
806 /* new values from dialog window */
807 void glob_path_dialog(t_pd
*dummy
, t_symbol
*s
, int argc
, t_atom
*argv
)
810 namelist_free(pd_path
);
812 for (i
= 0; i
< argc
; i
++)
814 t_symbol
*s
= atom_getsymbolarg(i
, argc
, argv
);
816 sys_addpath(s
->s_name
);