From 1f016c21cfd30ba1d602727cc316f239bbae7f48 Mon Sep 17 00:00:00 2001 From: Miller Puckette <msp@ucsd.edu> Date: Mon, 14 Jan 2008 18:16:19 -0800 Subject: [PATCH] took various small patches --- doc/5.reference/swap-help.pd | 61 +- doc/5.reference/trigger-help.pd | 2 +- src/m_class.c | 6 +- src/m_pd.h | 3 +- src/s_inter.c | 6 +- src/s_main.c | 2 +- src/s_main.c.orig | 1013 +++++++++++++++++++++++++++++++ src/s_path.c | 34 +- src/s_path.c.orig | 580 ++++++++++++++++++ src/x_connective.c | 2 +- 10 files changed, 1667 insertions(+), 42 deletions(-) create mode 100644 src/s_main.c.orig create mode 100644 src/s_path.c.orig diff --git a/doc/5.reference/swap-help.pd b/doc/5.reference/swap-help.pd index 987a58441..039e5659e 100644 --- a/doc/5.reference/swap-help.pd +++ b/doc/5.reference/swap-help.pd @@ -1,20 +1,41 @@ -#N canvas 376 130 488 326 12; -#X msg 67 124 bang; -#X floatatom 67 252; -#X floatatom 79 154; -#X floatatom 118 194; -#X obj 66 15 swap; -#X text 114 16 - SWAP TWO NUMBERS \, RESPECTING RIGHT-TO-LEFT ORDER; -#X text 284 309 updated for Pd version 0.27; -#X text 12 42 The swap object stores numbers from its left inlet to output on its right inlet -- after repeating its right hand input out the left.; -#X text 112 123 outputs 2 stored values; -#X obj 67 226 swap 6.5; -#X text 110 154 sets second value and outputs both; -#X text 150 195 sets first value; -#X text 142 226 creation argument initializes first value; -#X floatatom 118 254; -#X connect 0 0 9 0; -#X connect 2 0 9 0; -#X connect 3 0 9 1; -#X connect 9 0 1 0; -#X connect 9 1 13 0; +#N canvas 475 187 615 593 12; +#X msg 72 167 bang; +#X floatatom 72 292 0 0 0 0 - - -; +#X floatatom 84 200 0 0 0 0 - - -; +#X floatatom 139 237 0 0 0 0 - - -; +#X obj 33 15 swap; +#X text 81 16 - SWAP TWO NUMBERS \, RESPECTING RIGHT-TO-LEFT ORDER +; +#X text 117 166 outputs 2 stored values; +#X obj 72 266 swap 6.5; +#X text 115 200 sets second value and outputs both; +#X text 171 238 sets first value; +#X text 157 266 creation argument initializes first value; +#X floatatom 139 291 0 0 0 0 - - -; +#X obj 139 331 print right; +#X obj 72 367 print left; +#X text 43 427 A common use of swap is to reverse the operands in arithmetic +objects like this:; +#X obj 72 491 swap; +#X obj 72 519 -; +#X floatatom 72 541 5 0 0 0 - - -; +#X floatatom 103 469 3 0 0 0 - - -; +#X floatatom 72 469 3 0 0 0 - - -; +#X text 291 549 updated for Pd version 0.41; +#X text 32 52 The swap object swaps the positions of two incoming numbers. +The number coming in through the right inlet will be sent to the left +outlet and the number coming in left will come out right. Only the +left inlet is hot and triggers output on both outlets. Output order +is right to left as in [trigger].; +#X connect 0 0 7 0; +#X connect 1 0 13 0; +#X connect 2 0 7 0; +#X connect 3 0 7 1; +#X connect 7 0 1 0; +#X connect 7 1 11 0; +#X connect 11 0 12 0; +#X connect 15 0 16 0; +#X connect 15 1 16 1; +#X connect 16 0 17 0; +#X connect 18 0 15 1; +#X connect 19 0 15 0; diff --git a/doc/5.reference/trigger-help.pd b/doc/5.reference/trigger-help.pd index a32d5defc..3fae71128 100644 --- a/doc/5.reference/trigger-help.pd +++ b/doc/5.reference/trigger-help.pd @@ -14,7 +14,7 @@ #X text 39 59 The trigger object outputs its input from right to left \, converting to the types indicated by its creation arguments. There is also a "pointer" argument type (see the pointer object.); -#X obj 381 293 t f b l s a; +#X obj 381 293 t f b s l a; #X msg 466 167 dog my cats; #X obj 466 199 trigger bang anything; #X obj 374 242 print x5; diff --git a/src/m_class.c b/src/m_class.c index 622fbd2da..ab0b86bed 100644 --- a/src/m_class.c +++ b/src/m_class.c @@ -459,12 +459,12 @@ t_propertiesfn class_getpropertiesfn(t_class *c) static t_symbol *symhash[HASHSIZE]; -t_symbol *dogensym(char *s, t_symbol *oldsym) +t_symbol *dogensym(const char *s, t_symbol *oldsym) { t_symbol **sym1, *sym2; unsigned int hash1 = 0, hash2 = 0; int length = 0; - char *s2 = s; + const char *s2 = s; while (*s2) { hash1 += *s2; @@ -491,7 +491,7 @@ t_symbol *dogensym(char *s, t_symbol *oldsym) return (sym2); } -t_symbol *gensym(char *s) +t_symbol *gensym(const char *s) { return(dogensym(s, 0)); } diff --git a/src/m_pd.h b/src/m_pd.h index c92ba837c..25d811279 100644 --- a/src/m_pd.h +++ b/src/m_pd.h @@ -225,7 +225,7 @@ EXTERN t_symbol s_; /* --------- prototypes from the central message system ----------- */ EXTERN void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv); EXTERN void pd_forwardmess(t_pd *x, int argc, t_atom *argv); -EXTERN t_symbol *gensym(char *s); +EXTERN t_symbol *gensym(const char *s); EXTERN t_gotfn getfn(t_pd *x, t_symbol *s); EXTERN t_gotfn zgetfn(t_pd *x, t_symbol *s); EXTERN void nullfn(void); @@ -417,6 +417,7 @@ EXTERN char *class_gethelpname(t_class *c); EXTERN void class_setdrawcommand(t_class *c); EXTERN int class_isdrawcommand(t_class *c); EXTERN void class_domainsignalin(t_class *c, int onset); +EXTERN void class_set_extern_dir(t_symbol *s); #define CLASS_MAINSIGNALIN(c, type, field) \ class_domainsignalin(c, (char *)(&((type *)0)->field) - (char *)0) diff --git a/src/s_inter.c b/src/s_inter.c index 816e6207a..85a5af306 100644 --- a/src/s_inter.c +++ b/src/s_inter.c @@ -250,12 +250,14 @@ static void sys_huphandler(int n) void sys_setalarm(int microsec) { struct itimerval gonzo; + int sec = (int)(microsec/1000000); + microsec %= 1000000; #if 0 - fprintf(stderr, "timer %d\n", microsec); + fprintf(stderr, "timer %d:%d\n", sec, microsec); #endif gonzo.it_interval.tv_sec = 0; gonzo.it_interval.tv_usec = 0; - gonzo.it_value.tv_sec = 0; + gonzo.it_value.tv_sec = sec; gonzo.it_value.tv_usec = microsec; if (microsec) sys_signal(SIGALRM, sys_alarmhandler); diff --git a/src/s_main.c b/src/s_main.c index 52795cfef..3002937f1 100644 --- a/src/s_main.c +++ b/src/s_main.c @@ -295,7 +295,7 @@ int sys_main(int argc, char **argv) HINSTANCE ntdll; char filename[MAXPDSTRING]; - sprintf(filename, "%s.dll", sys_externalschedlibname); + snprintf(filename, sizeof(filename), "%s.dll", sys_externalschedlibname); sys_bashfilename(filename, filename); ntdll = LoadLibrary(filename); if (!ntdll) diff --git a/src/s_main.c.orig b/src/s_main.c.orig new file mode 100644 index 000000000..52795cfef --- /dev/null +++ b/src/s_main.c.orig @@ -0,0 +1,1013 @@ +/* Copyright (c) 1997-1999 Miller Puckette and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "m_imp.h" +#include "s_stuff.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <limits.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <stdlib.h> + +#ifdef UNISTD +#include <unistd.h> +#endif +#ifdef MSW +#include <io.h> +#include <windows.h> +#include <winbase.h> +#endif + +char *pd_version; +char pd_compiletime[] = __TIME__; +char pd_compiledate[] = __DATE__; + +void pd_init(void); +int sys_argparse(int argc, char **argv); +void sys_findprogdir(char *progname); +int sys_startgui(const char *guipath); +int sys_rcfile(void); +int m_mainloop(void); +void sys_addhelppath(char *p); +#ifdef USEAPI_ALSA +void alsa_adddev(char *name); +#endif + +int sys_debuglevel; +int sys_verbose; +int sys_noloadbang; +int sys_nogui; +int sys_hipriority = -1; /* -1 = don't care; 0 = no; 1 = yes */ +int sys_guisetportnumber; /* if started from the GUI, this is the port # */ +int sys_nosleep = 0; /* skip all "sleep" calls and spin instead */ + +char *sys_guicmd; +t_symbol *sys_libdir; +static t_symbol *sys_guidir; +static t_namelist *sys_openlist; +static t_namelist *sys_messagelist; +static int sys_version; +int sys_oldtclversion; /* hack to warn g_rtext.c about old text sel */ + +int sys_nmidiout = -1; +int sys_nmidiin = -1; +int sys_midiindevlist[MAXMIDIINDEV] = {1}; +int sys_midioutdevlist[MAXMIDIOUTDEV] = {1}; + +char sys_font[100] = +#ifdef MSW + "Courier"; +#else + "Courier"; +#endif +char sys_fontweight[] = "bold "; /* currently only used for iemguis */ +static int sys_main_srate; +static int sys_main_advance; +static int sys_main_callback; +static int sys_listplease; + +int sys_externalschedlib; +char sys_externalschedlibname[MAXPDSTRING]; +int sys_extraflags; +char sys_extraflagsstring[MAXPDSTRING]; + + + /* here the "-1" counts signify that the corresponding vector hasn't been + specified in command line arguments; sys_set_audio_settings will detect it + and fill things in. */ +static int sys_nsoundin = -1; +static int sys_nsoundout = -1; +static int sys_soundindevlist[MAXAUDIOINDEV]; +static int sys_soundoutdevlist[MAXAUDIOOUTDEV]; + +static int sys_nchin = -1; +static int sys_nchout = -1; +static int sys_chinlist[MAXAUDIOINDEV]; +static int sys_choutlist[MAXAUDIOOUTDEV]; + +t_sample* get_sys_soundout() { return sys_soundout; } +t_sample* get_sys_soundin() { return sys_soundin; } +int* get_sys_main_advance() { return &sys_main_advance; } +double* get_sys_time_per_dsp_tick() { return &sys_time_per_dsp_tick; } +int* get_sys_schedblocksize() { return &sys_schedblocksize; } +double* get_sys_time() { return &sys_time; } +t_float* get_sys_dacsr() { return &sys_dacsr; } +int* get_sys_sleepgrain() { return &sys_sleepgrain; } +int* get_sys_schedadvance() { return &sys_schedadvance; } + +typedef struct _fontinfo +{ + int fi_fontsize; + int fi_maxwidth; + int fi_maxheight; + int fi_hostfontsize; + int fi_width; + int fi_height; +} t_fontinfo; + + /* these give the nominal point size and maximum height of the characters + in the six fonts. */ + +static t_fontinfo sys_fontlist[] = { + {8, 6, 10, 0, 0, 0}, {10, 7, 13, 0, 0, 0}, {12, 9, 16, 0, 0, 0}, + {16, 10, 20, 0, 0, 0}, {24, 15, 25, 0, 0, 0}, {36, 25, 45, 0, 0, 0}}; +#define NFONT (sizeof(sys_fontlist)/sizeof(*sys_fontlist)) + +/* here are the actual font size structs on msp's systems: +MSW: +font 8 5 9 8 5 11 +font 10 7 13 10 6 13 +font 12 9 16 14 8 16 +font 16 10 20 16 10 18 +font 24 15 25 16 10 18 +font 36 25 42 36 22 41 + +linux: +font 8 5 9 8 5 9 +font 10 7 13 12 7 13 +font 12 9 16 14 9 15 +font 16 10 20 16 10 19 +font 24 15 25 24 15 24 +font 36 25 42 36 22 41 +*/ + +static t_fontinfo *sys_findfont(int fontsize) +{ + unsigned int i; + t_fontinfo *fi; + for (i = 0, fi = sys_fontlist; i < (NFONT-1); i++, fi++) + if (fontsize < fi[1].fi_fontsize) return (fi); + return (sys_fontlist + (NFONT-1)); +} + +int sys_nearestfontsize(int fontsize) +{ + return (sys_findfont(fontsize)->fi_fontsize); +} + +int sys_hostfontsize(int fontsize) +{ + return (sys_findfont(fontsize)->fi_hostfontsize); +} + +int sys_fontwidth(int fontsize) +{ + return (sys_findfont(fontsize)->fi_width); +} + +int sys_fontheight(int fontsize) +{ + return (sys_findfont(fontsize)->fi_height); +} + +int sys_defaultfont; +#define DEFAULTFONT 10 + +static void openit(const char *dirname, const char *filename) +{ + char dirbuf[MAXPDSTRING], *nameptr; + int fd = open_via_path(dirname, filename, "", dirbuf, &nameptr, + MAXPDSTRING, 0); + if (fd >= 0) + { + close (fd); + glob_evalfile(0, gensym(nameptr), gensym(dirbuf)); + } + else + error("%s: can't open", filename); +} + +/* this is called from the gui process. The first argument is the cwd, and +succeeding args give the widths and heights of known fonts. We wait until +these are known to open files and send messages specified on the command line. +We ask the GUI to specify the "cwd" in case we don't have a local OS to get it +from; for instance we could be some kind of RT embedded system. However, to +really make this make sense we would have to implement +open(), read(), etc, calls to be served somehow from the GUI too. */ + +void glob_initfromgui(void *dummy, t_symbol *s, int argc, t_atom *argv) +{ + char *cwd = atom_getsymbolarg(0, argc, argv)->s_name; + t_namelist *nl; + unsigned int i; + int j; + int nhostfont = (argc-2)/3; + sys_oldtclversion = atom_getfloatarg(1, argc, argv); + if (argc != 2 + 3 * nhostfont) bug("glob_initfromgui"); + for (i = 0; i < NFONT; i++) + { + int best = 0; + int wantheight = sys_fontlist[i].fi_maxheight; + int wantwidth = sys_fontlist[i].fi_maxwidth; + for (j = 1; j < nhostfont; j++) + { + if (atom_getintarg(3 * j + 4, argc, argv) <= wantheight && + atom_getintarg(3 * j + 3, argc, argv) <= wantwidth) + best = j; + } + /* best is now the host font index for the desired font index i. */ + sys_fontlist[i].fi_hostfontsize = + atom_getintarg(3 * best + 2, argc, argv); + sys_fontlist[i].fi_width = atom_getintarg(3 * best + 3, argc, argv); + sys_fontlist[i].fi_height = atom_getintarg(3 * best + 4, argc, argv); + } +#if 0 + for (i = 0; i < 6; i++) + fprintf(stderr, "font (%d %d %d) -> (%d %d %d)\n", + sys_fontlist[i].fi_fontsize, + sys_fontlist[i].fi_maxwidth, + sys_fontlist[i].fi_maxheight, + sys_fontlist[i].fi_hostfontsize, + sys_fontlist[i].fi_width, + sys_fontlist[i].fi_height); +#endif + /* load dynamic libraries specified with "-lib" args */ + for (nl = sys_externlist; nl; nl = nl->nl_next) + if (!sys_load_lib(0, nl->nl_string)) + post("%s: can't load library", nl->nl_string); + /* open patches specifies with "-open" args */ + for (nl = sys_openlist; nl; nl = nl->nl_next) + openit(cwd, nl->nl_string); + namelist_free(sys_openlist); + sys_openlist = 0; + /* send messages specified with "-send" args */ + for (nl = sys_messagelist; nl; nl = nl->nl_next) + { + t_binbuf *b = binbuf_new(); + binbuf_text(b, nl->nl_string, strlen(nl->nl_string)); + binbuf_eval(b, 0, 0, 0); + binbuf_free(b); + } + namelist_free(sys_messagelist); + sys_messagelist = 0; +} + +static void sys_afterargparse(void); + +static void pd_makeversion(void) +{ + char foo[100]; + sprintf(foo, "Pd version %d.%d-%d%s\n",PD_MAJOR_VERSION, + PD_MINOR_VERSION,PD_BUGFIX_VERSION,PD_TEST_VERSION); + pd_version = malloc(strlen(foo)+1); + strcpy(pd_version, foo); +} + +/* this is called from main() in s_entry.c */ +int sys_main(int argc, char **argv) +{ + int i, noprefs; + sys_externalschedlib = 0; + sys_extraflags = 0; +#ifdef PD_DEBUG + fprintf(stderr, "Pd: COMPILED FOR DEBUGGING\n"); +#endif + pd_init(); /* start the message system */ + sys_findprogdir(argv[0]); /* set sys_progname, guipath */ + for (i = noprefs = 0; i < argc; i++) /* prescan args for noprefs */ + if (!strcmp(argv[i], "-noprefs")) + noprefs = 1; + if (!noprefs) + sys_loadpreferences(); /* load default settings */ +#ifndef MSW + sys_rcfile(); /* parse the startup file */ +#endif + if (sys_argparse(argc-1, argv+1)) /* parse cmd line */ + return (1); + sys_afterargparse(); /* post-argparse settings */ + /* build version string from defines in m_pd.h */ + pd_makeversion(); + if (sys_verbose || sys_version) fprintf(stderr, "%scompiled %s %s\n", + pd_version, pd_compiletime, pd_compiledate); + if (sys_version) /* if we were just asked our version, exit here. */ + return (0); + if (sys_startgui(sys_guidir->s_name)) /* start the gui */ + return(1); + if (sys_externalschedlib) + { +#ifdef MSW + typedef int (*t_externalschedlibmain)(char *); + t_externalschedlibmain externalmainfunc; + HINSTANCE ntdll; + char filename[MAXPDSTRING]; + + sprintf(filename, "%s.dll", sys_externalschedlibname); + sys_bashfilename(filename, filename); + ntdll = LoadLibrary(filename); + if (!ntdll) + { + post("%s: couldn't load external scheduler lib ", filename); + return (0); + } + externalmainfunc = (t_externalschedlibmain)GetProcAddress(ntdll, + "main"); + return((*externalmainfunc)(sys_extraflagsstring)); +#else + return (0); +#endif + } + else + { + /* open audio and MIDI */ + sys_reopen_midi(); + sys_reopen_audio(); + /* run scheduler until it quits */ + return (m_mainloop()); + } +} + +static char *(usagemessage[]) = { +"usage: pd [-flags] [file]...\n", +"\naudio configuration flags:\n", +"-r <n> -- specify sample rate\n", +"-audioindev ... -- audio in devices; e.g., \"1,3\" for first and third\n", +"-audiooutdev ... -- audio out devices (same)\n", +"-audiodev ... -- specify input and output together\n", +"-inchannels ... -- audio input channels (by device, like \"2\" or \"16,8\")\n", +"-outchannels ... -- number of audio out channels (same)\n", +"-channels ... -- specify both input and output channels\n", +"-audiobuf <n> -- specify size of audio buffer in msec\n", +"-blocksize <n> -- specify audio I/O block size in sample frames\n", +"-sleepgrain <n> -- specify number of milliseconds to sleep when idle\n", +"-nodac -- suppress audio output\n", +"-noadc -- suppress audio input\n", +"-noaudio -- suppress audio input and output (-nosound is synonym) \n", +"-listdev -- list audio and MIDI devices\n", + +#ifdef USEAPI_OSS +"-oss -- use OSS audio API\n", +"-32bit ----- allow 32 bit OSS audio (for RME Hammerfall)\n", +#endif + +#ifdef USEAPI_ALSA +"-alsa -- use ALSA audio API\n", +"-alsaadd <name> -- add an ALSA device name to list\n", +#endif + +#ifdef USEAPI_JACK +"-jack -- use JACK audio API\n", +#endif + +#ifdef USEAPI_PORTAUDIO +#ifdef MSW +"-asio -- use ASIO audio driver (via Portaudio)\n", +"-pa -- synonym for -asio\n", +#else +"-pa -- use Portaudio API\n", +#endif +#endif + +#ifdef USEAPI_MMIO +"-mmio -- use MMIO audio API (default for Windows)\n", +#endif +" (default audio API for this platform: ", API_DEFSTRING, ")\n\n", + +"\nMIDI configuration flags:\n", +"-midiindev ... -- midi in device list; e.g., \"1,3\" for first and third\n", +"-midioutdev ... -- midi out device list, same format\n", +"-mididev ... -- specify -midioutdev and -midiindev together\n", +"-nomidiin -- suppress MIDI input\n", +"-nomidiout -- suppress MIDI output\n", +"-nomidi -- suppress MIDI input and output\n", +#ifdef USEAPI_ALSA +"-alsamidi -- use ALSA midi API\n", +#endif + + +"\nother flags:\n", +"-path <path> -- add to file search path\n", +"-nostdpath -- don't search standard (\"extra\") directory\n", +"-stdpath -- search standard directory (true by default)\n", +"-helppath <path> -- add to help file search path\n", +"-open <file> -- open file(s) on startup\n", +"-lib <file> -- load object library(s)\n", +"-font-size <n> -- specify default font size in points\n", +"-font-face <name> -- specify default font\n", +"-font-weight <name>-- specify default font weight (normal or bold)\n", +"-verbose -- extra printout on startup and when searching for files\n", +"-version -- don't run Pd; just print out which version it is \n", +"-d <n> -- specify debug level\n", +"-noloadbang -- suppress all loadbangs\n", +"-stderr -- send printout to standard error instead of GUI\n", +"-nogui -- suppress starting the GUI\n", +"-guiport <n> -- connect to pre-existing GUI over port <n>\n", +"-guicmd \"cmd...\" -- start alternatve GUI program (e.g., remote via ssh)\n", +"-send \"msg...\" -- send a message at startup, after patches are loaded\n", +"-noprefs -- suppress loading preferences on startup\n", +#ifdef UNISTD +"-rt or -realtime -- use real-time priority\n", +"-nrt -- don't use real-time priority\n", +#endif +"-nosleep -- spin, don't sleep (may lower latency on multi-CPUs)\n", +}; + +static void sys_parsedevlist(int *np, int *vecp, int max, char *str) +{ + int n = 0; + while (n < max) + { + if (!*str) break; + else + { + char *endp; + vecp[n] = strtol(str, &endp, 10); + if (endp == str) + break; + n++; + if (!endp) + break; + str = endp + 1; + } + } + *np = n; +} + +static int sys_getmultidevchannels(int n, int *devlist) +{ + int sum = 0; + if (n<0)return(-1); + if (n==0)return 0; + while(n--)sum+=*devlist++; + return sum; +} + + + /* this routine tries to figure out where to find the auxilliary files + Pd will need to run. This is either done by looking at the command line + invokation for Pd, or if that fails, by consulting the variable + INSTALL_PREFIX. In MSW, we don't try to use INSTALL_PREFIX. */ +void sys_findprogdir(char *progname) +{ + char sbuf[MAXPDSTRING], sbuf2[MAXPDSTRING], *sp; + char *lastslash; +#ifdef UNISTD + struct stat statbuf; +#endif + + /* find out by what string Pd was invoked; put answer in "sbuf". */ +#ifdef MSW + GetModuleFileName(NULL, sbuf2, sizeof(sbuf2)); + sbuf2[MAXPDSTRING-1] = 0; + sys_unbashfilename(sbuf2, sbuf); +#endif /* MSW */ +#ifdef UNISTD + strncpy(sbuf, progname, MAXPDSTRING); + sbuf[MAXPDSTRING-1] = 0; +#endif + lastslash = strrchr(sbuf, '/'); + if (lastslash) + { + /* bash last slash to zero so that sbuf is directory pd was in, + e.g., ~/pd/bin */ + *lastslash = 0; + /* go back to the parent from there, e.g., ~/pd */ + lastslash = strrchr(sbuf, '/'); + if (lastslash) + { + strncpy(sbuf2, sbuf, lastslash-sbuf); + sbuf2[lastslash-sbuf] = 0; + } + else strcpy(sbuf2, ".."); + } + else + { + /* no slashes found. Try INSTALL_PREFIX. */ +#ifdef INSTALL_PREFIX + strcpy(sbuf2, INSTALL_PREFIX); +#else + strcpy(sbuf2, "."); +#endif + } + /* now we believe sbuf2 holds the parent directory of the directory + pd was found in. We now want to infer the "lib" directory and the + "gui" directory. In "simple" unix installations, the layout is + .../bin/pd + .../bin/pd-gui + .../doc + and in "complicated" unix installations, it's: + .../bin/pd + .../lib/pd/bin/pd-gui + .../lib/pd/doc + To decide which, we stat .../lib/pd; if that exists, we assume it's + the complicated layout. In MSW, it's the "simple" layout, but + the gui program is straight wish80: + .../bin/pd + .../bin/wish80.exe + .../doc + */ +#ifdef MSW + sys_libdir = gensym(sbuf2); + sys_guidir = &s_; /* in MSW the guipath just depends on the libdir */ +#else + strncpy(sbuf, sbuf2, MAXPDSTRING-30); + sbuf[MAXPDSTRING-30] = 0; + strcat(sbuf, "/lib/pd"); + if (stat(sbuf, &statbuf) >= 0) + { + /* complicated layout: lib dir is the one we just stat-ed above */ + sys_libdir = gensym(sbuf); + /* gui lives in .../lib/pd/bin */ + strncpy(sbuf, sbuf2, MAXPDSTRING-30); + sbuf[MAXPDSTRING-30] = 0; + strcat(sbuf, "/lib/pd/bin"); + sys_guidir = gensym(sbuf); + } + else + { + /* simple layout: lib dir is the parent */ + sys_libdir = gensym(sbuf2); + /* gui lives in .../bin */ + strncpy(sbuf, sbuf2, MAXPDSTRING-30); + sbuf[MAXPDSTRING-30] = 0; + strcat(sbuf, "/bin"); + sys_guidir = gensym(sbuf); + } +#endif +} + +#ifdef MSW +static int sys_mmio = 1; +#else +static int sys_mmio = 0; +#endif + +int sys_argparse(int argc, char **argv) +{ + char sbuf[MAXPDSTRING]; + int i; + while ((argc > 0) && **argv == '-') + { + if (!strcmp(*argv, "-r") && argc > 1 && + sscanf(argv[1], "%d", &sys_main_srate) >= 1) + { + argc -= 2; + argv += 2; + } + else if (!strcmp(*argv, "-inchannels") && (argc > 1)) + { + sys_parsedevlist(&sys_nchin, + sys_chinlist, MAXAUDIOINDEV, argv[1]); + + if (!sys_nchin) + goto usage; + + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-outchannels") && (argc > 1)) + { + sys_parsedevlist(&sys_nchout, sys_choutlist, + MAXAUDIOOUTDEV, argv[1]); + + if (!sys_nchout) + goto usage; + + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-channels") && (argc > 1)) + { + sys_parsedevlist(&sys_nchin, sys_chinlist,MAXAUDIOINDEV, + argv[1]); + sys_parsedevlist(&sys_nchout, sys_choutlist,MAXAUDIOOUTDEV, + argv[1]); + + if (!sys_nchout) + goto usage; + + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-soundbuf") || !strcmp(*argv, "-audiobuf") && (argc > 1)) + { + sys_main_advance = atoi(argv[1]); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-callback")) + { + sys_main_callback = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-blocksize")) + { + sys_setblocksize(atoi(argv[1])); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-sleepgrain") && (argc > 1)) + { + sys_sleepgrain = 1000 * atof(argv[1]); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-nodac")) + { + sys_nsoundout=0; + sys_nchout = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-noadc")) + { + sys_nsoundin=0; + sys_nchin = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-nosound") || !strcmp(*argv, "-noaudio")) + { + sys_nsoundin=sys_nsoundout = 0; + sys_nchin = sys_nchout = 0; + argc--; argv++; + } +#ifdef USEAPI_OSS + else if (!strcmp(*argv, "-oss")) + { + sys_set_audio_api(API_OSS); + argc--; argv++; + } + else if (!strcmp(*argv, "-32bit")) + { + sys_set_audio_api(API_OSS); + oss_set32bit(); + argc--; argv++; + } +#endif +#ifdef USEAPI_ALSA + else if (!strcmp(*argv, "-alsa")) + { + sys_set_audio_api(API_ALSA); + argc--; argv++; + } + else if (!strcmp(*argv, "-alsaadd") && (argc > 1)) + { + if (argc > 1) + alsa_adddev(argv[1]); + else goto usage; + argc -= 2; argv +=2; + } + else if (!strcmp(*argv, "-alsamidi")) + { + sys_set_midi_api(API_ALSA); + argc--; argv++; + } +#endif +#ifdef USEAPI_JACK + else if (!strcmp(*argv, "-jack")) + { + sys_set_audio_api(API_JACK); + argc--; argv++; + } +#endif +#ifdef USEAPI_PORTAUDIO + else if (!strcmp(*argv, "-pa") || !strcmp(*argv, "-portaudio") +#ifdef MSW + || !strcmp(*argv, "-asio") +#endif + ) + { + sys_set_audio_api(API_PORTAUDIO); + sys_mmio = 0; + argc--; argv++; + } +#endif +#ifdef USEAPI_MMIO + else if (!strcmp(*argv, "-mmio")) + { + sys_set_audio_api(API_MMIO); + sys_mmio = 1; + argc--; argv++; + } +#endif + else if (!strcmp(*argv, "-nomidiin")) + { + sys_nmidiin = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-nomidiout")) + { + sys_nmidiout = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-nomidi")) + { + sys_nmidiin = sys_nmidiout = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-midiindev")) + { + sys_parsedevlist(&sys_nmidiin, sys_midiindevlist, MAXMIDIINDEV, + argv[1]); + if (!sys_nmidiin) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-midioutdev") && (argc > 1)) + { + sys_parsedevlist(&sys_nmidiout, sys_midioutdevlist, MAXMIDIOUTDEV, + argv[1]); + if (!sys_nmidiout) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-mididev") && (argc > 1)) + { + sys_parsedevlist(&sys_nmidiin, sys_midiindevlist, MAXMIDIINDEV, + argv[1]); + sys_parsedevlist(&sys_nmidiout, sys_midioutdevlist, MAXMIDIOUTDEV, + argv[1]); + if (!sys_nmidiout) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-path") && (argc > 1)) + { + sys_searchpath = namelist_append_files(sys_searchpath, argv[1]); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-nostdpath")) + { + sys_usestdpath = 0; + argc--; argv++; + } + else if (!strcmp(*argv, "-stdpath")) + { + sys_usestdpath = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-helppath")) + { + sys_helppath = namelist_append_files(sys_helppath, argv[1]); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-open") && argc > 1) + { + sys_openlist = namelist_append_files(sys_openlist, argv[1]); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-lib") && argc > 1) + { + sys_externlist = namelist_append_files(sys_externlist, argv[1]); + argc -= 2; argv += 2; + } + else if ((!strcmp(*argv, "-font-size") || !strcmp(*argv, "-font")) + && argc > 1) + { + sys_defaultfont = sys_nearestfontsize(atoi(argv[1])); + argc -= 2; + argv += 2; + } + else if ((!strcmp(*argv, "-font-face") || !strcmp(*argv, "-typeface")) + && argc > 1) + { + strncpy(sys_font,*(argv+1),sizeof(sys_font)-1); + sys_font[sizeof(sys_font)-1] = 0; + argc -= 2; + argv += 2; + } + else if (!strcmp(*argv, "-font-weight") && argc > 1) + { + strncpy(sys_fontweight,*(argv+1),sizeof(sys_fontweight)-1); + sys_fontweight[sizeof(sys_fontweight)-1] = 0; + argc -= 2; + argv += 2; + } + else if (!strcmp(*argv, "-verbose")) + { + sys_verbose++; + argc--; argv++; + } + else if (!strcmp(*argv, "-version")) + { + sys_version = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-d") && argc > 1 && + sscanf(argv[1], "%d", &sys_debuglevel) >= 1) + { + argc -= 2; + argv += 2; + } + else if (!strcmp(*argv, "-noloadbang")) + { + sys_noloadbang = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-nogui")) + { + sys_printtostderr = sys_nogui = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-guiport") && argc > 1 && + sscanf(argv[1], "%d", &sys_guisetportnumber) >= 1) + { + argc -= 2; + argv += 2; + } + else if (!strcmp(*argv, "-stderr")) + { + sys_printtostderr = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-guicmd") && argc > 1) + { + sys_guicmd = argv[1]; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-send") && argc > 1) + { + sys_messagelist = namelist_append(sys_messagelist, argv[1], 1); + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-listdev")) + { + sys_listplease = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-schedlib")) + { + sys_externalschedlib = 1; + strncpy(sys_externalschedlibname, argv[1], + sizeof(sys_externalschedlibname) - 1); + argv += 2; + argc -= 2; + } + else if (!strcmp(*argv, "-extraflags")) + { + sys_extraflags = 1; + strncpy(sys_extraflagsstring, argv[1], + sizeof(sys_extraflagsstring) - 1); + argv += 2; + argc -= 2; + } +#ifdef UNISTD + else if (!strcmp(*argv, "-rt") || !strcmp(*argv, "-realtime")) + { + sys_hipriority = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-nrt")) + { + sys_hipriority = 0; + argc--; argv++; + } +#endif + else if (!strcmp(*argv, "-nosleep")) + { + sys_nosleep = 1; + argc--; argv++; + } + else if (!strcmp(*argv, "-soundindev") || + !strcmp(*argv, "-audioindev")) + { + sys_parsedevlist(&sys_nsoundin, sys_soundindevlist, + MAXAUDIOINDEV, argv[1]); + if (!sys_nsoundin) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-soundoutdev") || + !strcmp(*argv, "-audiooutdev")) + { + sys_parsedevlist(&sys_nsoundout, sys_soundoutdevlist, + MAXAUDIOOUTDEV, argv[1]); + if (!sys_nsoundout) + goto usage; + argc -= 2; argv += 2; + } + else if ((!strcmp(*argv, "-sounddev") || !strcmp(*argv, "-audiodev")) + && (argc > 1)) + { + sys_parsedevlist(&sys_nsoundin, sys_soundindevlist, + MAXAUDIOINDEV, argv[1]); + sys_parsedevlist(&sys_nsoundout, sys_soundoutdevlist, + MAXAUDIOOUTDEV, argv[1]); + if (!sys_nsoundout) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(*argv, "-noprefs")) /* did this earlier */ + argc--, argv++; + else + { + unsigned int i; + usage: + for (i = 0; i < sizeof(usagemessage)/sizeof(*usagemessage); i++) + fprintf(stderr, "%s", usagemessage[i]); + return (1); + } + } + if (!sys_defaultfont) + sys_defaultfont = DEFAULTFONT; + for (; argc > 0; argc--, argv++) + sys_openlist = namelist_append_files(sys_openlist, *argv); + + + return (0); +} + +int sys_getblksize(void) +{ + return (DEFDACBLKSIZE); +} + + /* stuff to do, once, after calling sys_argparse() -- which may itself + be called more than once (first from "settings, second from .pdrc, then + from command-line arguments */ +static void sys_afterargparse(void) +{ + char sbuf[MAXPDSTRING]; + int i; + int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV]; + int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV]; + int nchindev, nchoutdev, rate, advance, callback; + int nmidiindev = 0, midiindev[MAXMIDIINDEV]; + int nmidioutdev = 0, midioutdev[MAXMIDIOUTDEV]; + /* add "extra" library to path */ + strncpy(sbuf, sys_libdir->s_name, MAXPDSTRING-30); + sbuf[MAXPDSTRING-30] = 0; + strcat(sbuf, "/extra"); + sys_setextrapath(sbuf); + /* add "doc/5.reference" library to helppath */ + strncpy(sbuf, sys_libdir->s_name, MAXPDSTRING-30); + sbuf[MAXPDSTRING-30] = 0; + strcat(sbuf, "/doc/5.reference"); + sys_helppath = namelist_append_files(sys_helppath, sbuf); + /* correct to make audio and MIDI device lists zero based. On + MMIO, however, "1" really means the second device (the first one + is "mapper" which is was not included when the command args were + set up, so we leave it that way for compatibility. */ + if (!sys_mmio) + { + for (i = 0; i < sys_nsoundin; i++) + sys_soundindevlist[i]--; + for (i = 0; i < sys_nsoundout; i++) + sys_soundoutdevlist[i]--; + } + for (i = 0; i < sys_nmidiin; i++) + sys_midiindevlist[i]--; + for (i = 0; i < sys_nmidiout; i++) + sys_midioutdevlist[i]--; + if (sys_listplease) + sys_listdevs(); + + /* get the current audio parameters. These are set + by the preferences mechanism (sys_loadpreferences()) or + else are the default. Overwrite them with any results + of argument parsing, and store them again. */ + sys_get_audio_params(&naudioindev, audioindev, chindev, + &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback); + if (sys_nchin >= 0) + { + nchindev = sys_nchin; + for (i = 0; i < nchindev; i++) + chindev[i] = sys_chinlist[i]; + } + else nchindev = naudioindev; + if (sys_nsoundin >= 0) + { + naudioindev = sys_nsoundin; + for (i = 0; i < naudioindev; i++) + audioindev[i] = sys_soundindevlist[i]; + } + + if (sys_nchout >= 0) + { + nchoutdev = sys_nchout; + for (i = 0; i < nchoutdev; i++) + choutdev[i] = sys_choutlist[i]; + } + else nchoutdev = naudiooutdev; + if (sys_nsoundout >= 0) + { + naudiooutdev = sys_nsoundout; + for (i = 0; i < naudiooutdev; i++) + audiooutdev[i] = sys_soundoutdevlist[i]; + } + sys_get_midi_params(&nmidiindev, midiindev, &nmidioutdev, midioutdev); + if (sys_nmidiin >= 0) + { + post("sys_nmidiin %d, nmidiindev %d", sys_nmidiin, nmidiindev); + nmidiindev = sys_nmidiin; + for (i = 0; i < nmidiindev; i++) + midiindev[i] = sys_midiindevlist[i]; + } + if (sys_nmidiout >= 0) + { + nmidioutdev = sys_nmidiout; + for (i = 0; i < nmidioutdev; i++) + midioutdev[i] = sys_midioutdevlist[i]; + } + if (sys_main_advance) + advance = sys_main_advance; + if (sys_main_srate) + rate = sys_main_srate; + if (sys_main_callback) + callback = sys_main_callback; + sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev, + naudiooutdev, audiooutdev, nchoutdev, choutdev, rate, advance, + callback); + sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev, 0); +} + +static void sys_addreferencepath(void) +{ + char sbuf[MAXPDSTRING]; +} diff --git a/src/s_path.c b/src/s_path.c index 0d9728619..f96ea872f 100644 --- a/src/s_path.c +++ b/src/s_path.c @@ -71,21 +71,29 @@ void sys_unbashfilename(const char *from, char *to) /******************* Utility functions used below ******************/ -/* copy until delimiter and return position after delimiter in string */ -/* if it was the last substring, return NULL */ - -static const char* strtokcpy(char *to, const char *from, int delim) +/*! + * \brief copy until delimiter + * + * \arg to destination buffer + * \arg to_len destination buffer length + * \arg from source buffer + * \arg delim string delimiter to stop copying on + * + * \return position after delimiter in string. If it was the last + * substring, return NULL. + */ +static const char *strtokcpy(char *to, size_t to_len, const char *from, char delim) { - int size = 0; + unsigned int i = 0; + + for (; i < (to_len - 1) && from[i] && from[i] != delim; i++) + to[i] = from[i]; + to[i] = '\0'; - while (from[size] != (char)delim && from[size] != '\0') - size++; + if (i && from[i] != '\0') + return from + i + 1; - strncpy(to,from,size); - to[size] = '\0'; - if (from[size] == '\0') return NULL; - if (size) return from+size+1; - else return NULL; + return NULL; } /* add a single item to a namelist. If "allowdup" is true, duplicates @@ -133,7 +141,7 @@ t_namelist *namelist_append_files(t_namelist *listwas, const char *s) npos = s; do { - npos = strtokcpy(temp, npos, SEPARATOR); + npos = strtokcpy(temp, sizeof(temp), npos, SEPARATOR); if (! *temp) continue; nl = namelist_append(nl, temp, 0); } diff --git a/src/s_path.c.orig b/src/s_path.c.orig new file mode 100644 index 000000000..0d9728619 --- /dev/null +++ b/src/s_path.c.orig @@ -0,0 +1,580 @@ +/* Copyright (c) 1999 Guenter Geiger and others. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* + * This file implements the loader for linux, which includes + * a little bit of path handling. + * + * Generalized by MSP to provide an open_via_path function + * and lists of files for all purposes. + */ + +/* #define DEBUG(x) x */ +#define DEBUG(x) + +#include <stdlib.h> +#ifdef UNISTD +#include <unistd.h> +#include <sys/stat.h> +#endif +#ifdef MSW +#include <io.h> +#endif + +#include <string.h> +#include "m_pd.h" +#include "m_imp.h" +#include "s_stuff.h" +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> + +#ifdef _LARGEFILE64_SOURCE +# define open open64 +# define lseek lseek64 +# define fstat fstat64 +# define stat stat64 +#endif + +t_namelist *sys_externlist; +t_namelist *sys_searchpath; +t_namelist *sys_helppath; + + /* change '/' characters to the system's native file separator */ +void sys_bashfilename(const char *from, char *to) +{ + char c; + while (c = *from++) + { +#ifdef MSW + if (c == '/') c = '\\'; +#endif + *to++ = c; + } + *to = 0; +} + + /* change the system's native file separator to '/' characters */ +void sys_unbashfilename(const char *from, char *to) +{ + char c; + while (c = *from++) + { +#ifdef MSW + if (c == '\\') c = '/'; +#endif + *to++ = c; + } + *to = 0; +} + +/******************* Utility functions used below ******************/ + +/* copy until delimiter and return position after delimiter in string */ +/* if it was the last substring, return NULL */ + +static const char* strtokcpy(char *to, const char *from, int delim) +{ + int size = 0; + + while (from[size] != (char)delim && from[size] != '\0') + size++; + + strncpy(to,from,size); + to[size] = '\0'; + if (from[size] == '\0') return NULL; + if (size) return from+size+1; + else return NULL; +} + +/* add a single item to a namelist. If "allowdup" is true, duplicates +may be added; othewise they're dropped. */ + +t_namelist *namelist_append(t_namelist *listwas, const char *s, int allowdup) +{ + t_namelist *nl, *nl2; + nl2 = (t_namelist *)(getbytes(sizeof(*nl))); + nl2->nl_next = 0; + nl2->nl_string = (char *)getbytes(strlen(s) + 1); + strcpy(nl2->nl_string, s); + sys_unbashfilename(nl2->nl_string, nl2->nl_string); + if (!listwas) + return (nl2); + else + { + for (nl = listwas; ;) + { + if (!allowdup && !strcmp(nl->nl_string, s)) + return (listwas); + if (!nl->nl_next) + break; + nl = nl->nl_next; + } + nl->nl_next = nl2; + } + return (listwas); +} + +/* add a colon-separated list of names to a namelist */ + +#ifdef MSW +#define SEPARATOR ';' /* in MSW the natural separator is semicolon instead */ +#else +#define SEPARATOR ':' +#endif + +t_namelist *namelist_append_files(t_namelist *listwas, const char *s) +{ + const char *npos; + char temp[MAXPDSTRING]; + t_namelist *nl = listwas, *rtn = listwas; + + npos = s; + do + { + npos = strtokcpy(temp, npos, SEPARATOR); + if (! *temp) continue; + nl = namelist_append(nl, temp, 0); + } + while (npos); + return (nl); +} + +void namelist_free(t_namelist *listwas) +{ + t_namelist *nl, *nl2; + for (nl = listwas; nl; nl = nl2) + { + nl2 = nl->nl_next; + t_freebytes(nl->nl_string, strlen(nl->nl_string) + 1); + t_freebytes(nl, sizeof(*nl)); + } +} + +char *namelist_get(t_namelist *namelist, int n) +{ + int i; + t_namelist *nl; + for (i = 0, nl = namelist; i < n && nl; i++, nl = nl->nl_next) + ; + return (nl ? nl->nl_string : 0); +} + +static t_namelist *pd_extrapath; + +int sys_usestdpath = 1; + +void sys_setextrapath(const char *p) +{ + namelist_free(pd_extrapath); + pd_extrapath = namelist_append(0, p, 0); +} + +#ifdef MSW +#define MSWOPENFLAG(bin) (bin ? _O_BINARY : _O_TEXT) +#else +#define MSWOPENFLAG(bin) 0 +#endif + + /* try to open a file in the directory "dir", named "name""ext", + for reading. "Name" may have slashes. The directory is copied to + "dirresult" which must be at least "size" bytes. "nameresult" is set + to point to the filename (copied elsewhere into the same buffer). + The "bin" flag requests opening for binary (which only makes a difference + on Windows). */ + +int sys_trytoopenone(const char *dir, const char *name, const char* ext, + char *dirresult, char **nameresult, unsigned int size, int bin) +{ + int fd; + if (strlen(dir) + strlen(name) + strlen(ext) + 4 > size) + return (-1); + strcpy(dirresult, dir); + if (*dirresult && dirresult[strlen(dirresult)-1] != '/') + strcat(dirresult, "/"); + strcat(dirresult, name); + strcat(dirresult, ext); + sys_bashfilename(dirresult, dirresult); + + DEBUG(post("looking for %s",dirresult)); + /* see if we can open the file for reading */ + if ((fd=open(dirresult,O_RDONLY | MSWOPENFLAG(bin))) >= 0) + { + /* in unix, further check that it's not a directory */ +#ifdef UNISTD + struct stat statbuf; + int ok = ((fstat(fd, &statbuf) >= 0) && + !S_ISDIR(statbuf.st_mode)); + if (!ok) + { + if (sys_verbose) post("tried %s; stat failed or directory", + dirresult); + close (fd); + fd = -1; + } + else +#endif + { + char *slash; + if (sys_verbose) post("tried %s and succeeded", dirresult); + sys_unbashfilename(dirresult, dirresult); + slash = strrchr(dirresult, '/'); + if (slash) + { + *slash = 0; + *nameresult = slash + 1; + } + else *nameresult = dirresult; + + return (fd); + } + } + else + { + if (sys_verbose) post("tried %s and failed", dirresult); + } + return (-1); +} + + /* check if we were given an absolute pathname, if so try to open it + and return 1 to signal the caller to cancel any path searches */ +int sys_open_absolute(const char *name, const char* ext, + char *dirresult, char **nameresult, unsigned int size, int bin, int *fdp) +{ + if (name[0] == '/' +#ifdef MSW + || (name[1] == ':' && name[2] == '/') +#endif + ) + { + char dirbuf[MAXPDSTRING]; + int dirlen = (strrchr(name, '/') - name); + if (dirlen > MAXPDSTRING-1) + dirlen = MAXPDSTRING-1; + strncpy(dirbuf, name, dirlen); + dirbuf[dirlen] = 0; + *fdp = sys_trytoopenone(dirbuf, name+(dirlen+1), ext, + dirresult, nameresult, size, bin); + return (1); + } + else return (0); +} + +/* search for a file in a specified directory, then along the globally +defined search path, using ext as filename extension. The +fd is returned, the directory ends up in the "dirresult" which must be at +least "size" bytes. "nameresult" is set to point to the filename, which +ends up in the same buffer as dirresult. Exception: +if the 'name' starts with a slash or a letter, colon, and slash in MSW, +there is no search and instead we just try to open the file literally. */ + +/* see also canvas_open() which, in addition, searches down the +canvas-specific path. */ + +static int do_open_via_path(const char *dir, const char *name, + const char *ext, char *dirresult, char **nameresult, unsigned int size, + int bin, t_namelist *searchpath) +{ + t_namelist *nl; + int fd = -1; + + /* first check if "name" is absolute (and if so, try to open) */ + if (sys_open_absolute(name, ext, dirresult, nameresult, size, bin, &fd)) + return (fd); + + /* otherwise "name" is relative; try the directory "dir" first. */ + if ((fd = sys_trytoopenone(dir, name, ext, + dirresult, nameresult, size, bin)) >= 0) + return (fd); + + /* next go through the search path */ + for (nl = searchpath; nl; nl = nl->nl_next) + if ((fd = sys_trytoopenone(nl->nl_string, name, ext, + dirresult, nameresult, size, bin)) >= 0) + return (fd); + + /* next look in "extra" */ + if (sys_usestdpath && + (fd = sys_trytoopenone(pd_extrapath->nl_string, name, ext, + dirresult, nameresult, size, bin)) >= 0) + return (fd); + + *dirresult = 0; + *nameresult = dirresult; + return (-1); +} + + /* open via path, using the global search path. */ +int open_via_path(const char *dir, const char *name, const char *ext, + char *dirresult, char **nameresult, unsigned int size, int bin) +{ + return (do_open_via_path(dir, name, ext, dirresult, nameresult, + size, bin, sys_searchpath)); +} + + /* Open a help file using the help search path. We expect the ".pd" + suffix here, even though we have to tear it back off for one of the + search attempts. */ +void open_via_helppath(const char *name, const char *dir) +{ + char realname[MAXPDSTRING], dirbuf[MAXPDSTRING], *basename; + /* make up a silly "dir" if none is supplied */ + const char *usedir = (*dir ? dir : "./"); + int fd; + + /* 1. "objectname-help.pd" */ + strncpy(realname, name, MAXPDSTRING-10); + realname[MAXPDSTRING-10] = 0; + if (strlen(realname) > 3 && !strcmp(realname+strlen(realname)-3, ".pd")) + realname[strlen(realname)-3] = 0; + strcat(realname, "-help.pd"); + if ((fd = do_open_via_path(dir, realname, "", dirbuf, &basename, + MAXPDSTRING, 0, sys_helppath)) >= 0) + goto gotone; + + /* 2. "help-objectname.pd" */ + strcpy(realname, "help-"); + strncat(realname, name, MAXPDSTRING-10); + realname[MAXPDSTRING-1] = 0; + if ((fd = do_open_via_path(dir, realname, "", dirbuf, &basename, + MAXPDSTRING, 0, sys_helppath)) >= 0) + goto gotone; + + /* 3. "objectname.pd" */ + if ((fd = do_open_via_path(dir, name, "", dirbuf, &basename, + MAXPDSTRING, 0, sys_helppath)) >= 0) + goto gotone; + post("sorry, couldn't find help patch for \"%s\"", name); + return; +gotone: + close (fd); + glob_evalfile(0, gensym((char*)basename), gensym(dirbuf)); +} + + +/* Startup file reading for linux and __APPLE__. As of 0.38 this will be +deprecated in favor of the "settings" mechanism */ + +int sys_argparse(int argc, char **argv); + +#ifndef MSW + +#define STARTUPNAME ".pdrc" +#define NUMARGS 1000 + +int sys_rcfile(void) +{ + FILE* file; + int i; + int k; + int rcargc; + char* rcargv[NUMARGS]; + char* buffer; + char fname[MAXPDSTRING], buf[1000], *home = getenv("HOME"); + int retval = 1; /* that's what we will return at the end; for now, let's think it'll be an error */ + + /* initialize rc-arg-array so we can safely clean up at the end */ + for (i = 1; i < NUMARGS-1; i++) + rcargv[i]=0; + + + /* parse a startup file */ + + *fname = '\0'; + + strncat(fname, home? home : ".", MAXPDSTRING-10); + strcat(fname, "/"); + + strcat(fname, STARTUPNAME); + + if (!(file = fopen(fname, "r"))) + return 1; + + post("reading startup file: %s", fname); + + rcargv[0] = "."; /* this no longer matters to sys_argparse() */ + + for (i = 1; i < NUMARGS-1; i++) + { + if (fscanf(file, "%999s", buf) < 0) + break; + buf[1000] = 0; + if (!(rcargv[i] = malloc(strlen(buf) + 1))) + goto cleanup; + strcpy(rcargv[i], buf); + } + if (i >= NUMARGS-1) + fprintf(stderr, "startup file too long; extra args dropped\n"); + rcargv[i] = 0; + + rcargc = i; + + /* parse the options */ + + fclose(file); + if (sys_verbose) + { + if (rcargv) + { + post("startup args from RC file:"); + for (i = 1; i < rcargc; i++) + post("%s", rcargv[i]); + } + else post("no RC file arguments found"); + } + if (sys_argparse(rcargc-1, rcargv+1)) + { + post("error parsing RC arguments"); + goto cleanup; + } + + retval=0; /* we made it without an error */ + + + cleanup: /* prevent memleak */ + for (i = 1; i < NUMARGS-1; i++) + if(rcargv[i])free(rcargv[i]); + + return(retval); +} +#endif /* MSW */ + +void sys_doflags( void) +{ + int i, beginstring = 0, state = 0, len = strlen(sys_flags->s_name); + int rcargc = 0; + char *rcargv[MAXPDSTRING]; + if (len > MAXPDSTRING) + { + post("flags: %s: too long", sys_flags->s_name); + return; + } + for (i = 0; i < len+1; i++) + { + int c = sys_flags->s_name[i]; + if (state == 0) + { + if (c && !isspace(c)) + { + beginstring = i; + state = 1; + } + } + else + { + if (!c || isspace(c)) + { + char *foo = malloc(i - beginstring + 1); + if (!foo) + return; + strncpy(foo, sys_flags->s_name + beginstring, i - beginstring); + foo[i - beginstring] = 0; + rcargv[rcargc] = foo; + rcargc++; + if (rcargc >= MAXPDSTRING) + break; + state = 0; + } + } + } + if (sys_argparse(rcargc, rcargv)) + post("error parsing startup arguments"); +} + +/* undo pdtl_encodedialog. This allows dialogs to send spaces, commas, + dollars, and semis down here. */ +t_symbol *sys_decodedialog(t_symbol *s) +{ + char buf[MAXPDSTRING], *sp = s->s_name; + int i; + if (*sp != '+') + bug("sys_decodedialog: %s", sp); + else sp++; + for (i = 0; i < MAXPDSTRING-1; i++, sp++) + { + if (!sp[0]) + break; + if (sp[0] == '+') + { + if (sp[1] == '_') + buf[i] = ' ', sp++; + else if (sp[1] == '+') + buf[i] = '+', sp++; + else if (sp[1] == 'c') + buf[i] = ',', sp++; + else if (sp[1] == 's') + buf[i] = ';', sp++; + else if (sp[1] == 'd') + buf[i] = '$', sp++; + else buf[i] = sp[0]; + } + else buf[i] = sp[0]; + } + buf[i] = 0; + return (gensym(buf)); +} + + + /* start a search path dialog window */ +void glob_start_path_dialog(t_pd *dummy) +{ + char buf[MAXPDSTRING]; + int i; + t_namelist *nl; + + sys_vgui("pd_set pd_path \"\"\n"); + for (nl = sys_searchpath, i = 0; nl; nl = nl->nl_next, i++) + sys_vgui("lappend pd_path \"%s\"\n", nl->nl_string); + sprintf(buf, "pdtk_path_dialog %%s %d %d\n", sys_usestdpath, sys_verbose); + gfxstub_new(&glob_pdobject, (void *)glob_start_path_dialog, buf); +} + + /* new values from dialog window */ +void glob_path_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) +{ + int i; + namelist_free(sys_searchpath); + sys_searchpath = 0; + sys_usestdpath = atom_getintarg(0, argc, argv); + sys_verbose = atom_getintarg(1, argc, argv); + for (i = 0; i < argc-2; i++) + { + t_symbol *s = sys_decodedialog(atom_getsymbolarg(i+2, argc, argv)); + if (*s->s_name) + sys_searchpath = namelist_append_files(sys_searchpath, s->s_name); + } +} + + /* start a startup dialog window */ +void glob_start_startup_dialog(t_pd *dummy) +{ + char buf[MAXPDSTRING]; + int i; + t_namelist *nl; + + sys_vgui("pd_set pd_startup \"\"\n"); + for (nl = sys_externlist, i = 0; nl; nl = nl->nl_next, i++) + sys_vgui("lappend pd_startup \"%s\"\n", nl->nl_string); + sprintf(buf, "pdtk_startup_dialog %%s %d \"%s\"\n", sys_defeatrt, + sys_flags->s_name); + gfxstub_new(&glob_pdobject, (void *)glob_start_startup_dialog, buf); +} + + /* new values from dialog window */ +void glob_startup_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) +{ + int i; + namelist_free(sys_externlist); + sys_externlist = 0; + sys_defeatrt = atom_getintarg(0, argc, argv); + sys_flags = sys_decodedialog(atom_getsymbolarg(1, argc, argv)); + for (i = 0; i < argc-2; i++) + { + t_symbol *s = sys_decodedialog(atom_getsymbolarg(i+2, argc, argv)); + if (*s->s_name) + sys_externlist = namelist_append_files(sys_externlist, s->s_name); + } +} + + diff --git a/src/x_connective.c b/src/x_connective.c index 2f291f506..8687154ea 100644 --- a/src/x_connective.c +++ b/src/x_connective.c @@ -1232,7 +1232,7 @@ static void makefilename_scanformat(t_makefilename *x) x->x_intconvert = 0; break; } - if (strchr("xXdiou",*str)!=0) { + if (strchr("xXdiouc",*str)!=0) { x->x_accept = A_FLOAT; x->x_intconvert = 1; break; -- GitLab