1
/* For use with emTeX set FONTPATH to "TEXTFM"
4
#define FONTPATH "TEXFONTS"
8
* This code reads in and handles the defaults for the program from the
9
* file config.sw. This entire file is a bit kludgy, sorry.
11
#include "dvips.h" /* The copyright notice in that file is included too! */
14
#include <kpathsea/c-ctype.h>
15
#include <kpathsea/c-pathch.h>
16
#include <kpathsea/c-stat.h>
17
#include <kpathsea/pathsearch.h>
18
#include <kpathsea/tex-file.h>
19
#include <kpathsea/variable.h>
22
* This is the structure definition for resident fonts. We use
23
* a small and simple hash table to handle these. We don't need
26
struct resfont *reshash[RESHASHPRIME] ;
28
* These are the external routines we use.
32
* These are the external variables we use.
34
extern char *realnameoffile ;
36
extern integer debug_flag;
38
extern integer pagecopies ;
39
extern int overridemag ;
40
extern long bytesleft ;
41
extern quarterword *raster ;
44
extern integer swmem, fontmem ;
46
extern char *tfmpath, *pictpath ;
49
extern char *figpath ;
50
extern char *configpath ;
51
extern char *headerpath ;
52
#ifdef SEARCH_SUBDIRECTORIES
53
extern char *fontsubdirpath ;
56
extern Boolean noenv ;
57
extern Boolean downloadpspk ;
59
extern char *flipath, *fliname ;
61
extern char *paperfmt ;
62
extern char *nextstring ;
63
extern char *maxstring ;
64
extern char *warningmsg ;
65
extern Boolean disablecomments ;
66
extern Boolean compressed ;
67
extern Boolean partialdownload ;
70
extern Boolean reverse ;
71
extern Boolean usesPSfonts ;
72
extern Boolean nosmallchars ;
73
extern Boolean removecomments ;
74
extern Boolean safetyenclose ;
75
extern Boolean dopprescan ;
76
extern integer maxsecsize ;
78
extern Boolean sepfiles ;
79
extern int actualdpi ;
80
extern int vactualdpi ;
82
extern int vmaxdrift ;
83
extern char *printer ;
84
extern char *mfmode, *mflandmode ;
85
extern int mfmode_option;
86
extern int secure_option;
87
extern int oname_option;
88
extern Boolean sendcontrolD ;
90
extern Boolean shiftlowchars ;
92
extern unsigned lastresortsizes[] ;
93
extern integer hoff, voff ;
94
extern struct papsiz *papsizes ;
95
extern Boolean secure ;
96
extern integer hpapersize, vpapersize ;
97
extern int landscape ;
99
* To maintain a list of document fonts, we use the following
102
struct header_list *ps_fonts_used ;
112
h = (h + h + *s++) % RESHASHPRIME ;
116
* Reverse the hash chains.
119
revpslists P1H(void) {
121
for (i=0; i<RESHASHPRIME; i++)
122
reshash[i] = (struct resfont *)revlist(reshash[i]) ;
125
* cleanres() marks all resident fonts as not being yet sent, except
126
* those marked with 2 meaning they were downloaded as part of the
127
* main prolog (not section prolog).
132
register struct resfont *p ;
133
for (i=0; i<RESHASHPRIME; i++)
134
for (p=reshash[i]; p; p=p->next)
139
* The routine that looks up a font name.
142
lookup P1C(char *, name)
146
for (p=reshash[hash(name)]; p!=NULL; p=p->next)
147
if (strcmp(p->Keyname, name)==0)
153
findPSname P1C(char *, name)
156
register struct resfont *p ;
157
for (i=0; i<RESHASHPRIME; i++)
158
for (p=reshash[i]; p; p=p->next) {
159
if (strcmp(p->PSname, name)==0)
166
* This routine adds an entry.
169
add_entry P6C(char *, TeXname, char *, PSname, char *, Fontfile,
170
char *, Vectfile, char *, specinfo, char *, downloadinfo)
176
p = (struct resfont *)mymalloc((integer)sizeof(struct resfont)) ;
177
p->Keyname = TeXname ;
179
p->Fontfile = Fontfile;
180
p->Vectfile = Vectfile;
181
p->TeXname = TeXname ;
182
p->specialinstructions = specinfo ;
183
if (downloadinfo && *downloadinfo)
184
p->downloadheader = downloadinfo ;
186
p->downloadheader = 0 ;
188
p->next = reshash[h] ;
193
* Now our residentfont routine. Returns the number of characters in
194
* this font, based on the TFM file.
196
extern char *infont ;
198
residentfont P1C(register fontdesctype *, curfnt)
200
register shalfword i ;
204
* First we determine if we can find this font in the resident list.
207
return 0 ; /* resident fonts never have a nonstandard font area */
208
if ((p=lookup(curfnt->name))==NULL)
211
* This is not yet the correct way to do things, but it is useful as it
212
* is so we leave it in. The problem: if resident Times-Roman is
213
* re-encoded, then it will be downloaded as bitmaps; this is not
214
* right. The solution will be to introduce two types of `<'
215
* directives, one that downloads fonts and one that downloads
216
* short headers that are innocuous.
218
if (p->Fontfile && downloadpspk) {
221
(void)fprintf(stderr,"Using PK font %s for <%s>.\n",
222
curfnt->name, p->PSname) ;
227
* We clear out some pointers:
231
(void)fprintf(stderr,"Font %s <%s> is resident.\n",
232
curfnt->name, p->PSname) ;
234
curfnt->resfont = p ;
235
curfnt->name = p->TeXname ;
236
for (i=0; i<256; i++) {
237
curfnt->chardesc[i].TFMwidth = 0 ;
238
curfnt->chardesc[i].packptr = NULL ;
239
curfnt->chardesc[i].pixelwidth = 0 ;
240
curfnt->chardesc[i].flags = 0 ;
241
curfnt->chardesc[i].flags2 = 0 ;
243
add_name(p->PSname, &ps_fonts_used) ;
245
* We include the font here. But we only should need to include the
246
* font if we have a stupid spooler; smart spoolers should be able
247
* to supply it automatically.
249
if (p->downloadheader) {
250
char *cp = p->downloadheader ;
256
while (*cp && *cp != ' ')
263
/* if (strstr(q,".pfa")||strstr(q,".pfb")||
264
strstr(q,".PFA")||strstr(q,".PFB"))
275
i = tfmload(curfnt) ;
281
#define INLINE_SIZE (2000)
282
static char was_inline[INLINE_SIZE] ;
283
static unsigned c_lineno;
285
bad_config P1C(char *, err)
287
fprintf (stderr, "%s:%d:", realnameoffile, c_lineno);
289
fprintf(stderr, " (%s)\n", was_inline) ;
294
* Get environment variables! These override entries in ./config.h.
295
* We substitute everything of the form ::, ^: or :$ with default,
296
* so a user can easily build on to the existing paths.
298
static char *getpath P2C(char *, who, char *, what)
301
register char *pp, *qq ;
304
for (pp=nextstring, qq=who; *qq;) {
305
if (*qq == PATHSEP) {
308
pp = pp + strlen(pp) ;
317
pp = pp + strlen(pp) ;
321
nextstring = pp + 1 ;
328
* We use this function so we can support strings delimited by
329
* double quotes with spaces in them. We also accept strings
330
* with spaces in them, but kill off any spaces at the end.
332
char *configstring P2C(char *, s, int, nullok)
334
char tstr[INLINE_SIZE] ;
337
while (*s && *s <= ' ')
341
while (*s != 10 && *s != 0 && *s != '"' && p < tstr+290)
344
while (*s && p < tstr+290)
346
while (*(p-1) <= ' ' && p > tstr)
350
if (p == tstr && ! nullok)
351
bad_config("bad string") ;
352
return newstring(tstr) ;
355
/* We use this in `getdefaults' to modify the kpathsea structure for the
356
paths we read. See kpathsea/tex-file.[ch]. */
357
#define SET_CLIENT_PATH(filefmt, val) \
358
kpse_format_info[filefmt].client_path = xstrdup (val)
361
* Now we have the getdefaults routine.
363
char *psmapfile = PSMAPFILE ;
365
getdefaults P1C(char *, s)
368
char PSname[INLINE_SIZE] ;
372
char *d = configpath ;
375
int canaddtopaper = 0 ;
377
if (printer == NULL) {
382
char *dvipsrc = kpse_var_value ("DVIPSRC");
384
if (dvipsrc && *dvipsrc) {
385
/* $DVIPSRC was set by user */
386
strcpy(PSname, dvipsrc);
389
/* No env var, looking into some kind of standard path. */
390
if (SearchPath(".;%HOME%;c:\\", ".dvipsrc", NULL,
393
/* search failed, we must put something into PSname. */
394
dvipsrc = kpse_var_expand(DVIPSRC);
396
strcpy(PSname, dvipsrc);
399
/* Else SearchPath has filled PSname with something */
401
/* remove any redundant path separators. Many configurations
402
can show up: c:\/.dvipsrc and so on ... */
405
for (p = q = PSname; *p && (p - PSname < INLINE_SIZE) ;
407
if (IS_DIR_SEP(*p)) {
408
*q = DIR_SEP; p++; q++;
409
while (*p && IS_DIR_SEP(*p)) p++;
416
if(!dvipsrc) dvipsrc = kpse_var_expand(DVIPSRC) ;
417
strcpy(PSname, dvipsrc ? dvipsrc : "~/.dvipsrc") ;
418
if(dvipsrc) free(dvipsrc) ;
421
#else /* ! KPATHSEA */
422
#ifndef VMCMS /* IBM: VM/CMS - don't have home directory on VMCMS */
426
#endif /* IBM: VM/CMS */
427
strcpy(PSname, DVIPSRC) ;
428
#endif /* KPATHSEA */
431
#if defined(MSDOS) || defined(OS2)
432
strcpy(PSname, printer) ;
433
strcat(PSname, ".cfg") ;
435
strcpy(PSname, "config.") ;
436
strcat(PSname, printer) ;
440
if ((deffile=search(configpath,PSname,READ))!=NULL) {
442
if ((deffile=search(d,PSname,READ))!=NULL) {
446
fprintf (stderr, "Reading dvips config file `%s':\n", realnameoffile);
450
while (fgets(was_inline, INLINE_SIZE, deffile)!=NULL) {
454
fprintf (stderr, "%s:%d:%s", realnameoffile, c_lineno, was_inline);
458
* We need to get rid of the newline.
460
for (p=was_inline; *p; p++) ;
461
while (p > was_inline && (*(p-1) == '\n' || *(p-1) == '\r')) {
464
if (was_inline[0] != '@')
466
switch (was_inline[0]) {
468
* Handling paper size information:
470
* If line is empty, then we clear out the paper size information
473
* If it is `@+', then we add to the current paper size info.
475
* If it is `name hsize vsize', then we start a new definition.
479
while (*p && *p <= ' ') p++ ;
481
papsizes = 0 ; /* throw away memory */
482
} else if (*p == '+') {
483
if (canaddtopaper == 0)
485
" @+ in config files must immediately following a @ lines") ;
487
*(nextstring-1) = '\n' ;/* IBM: VM/CMS - changed 10 to "\n" */
489
while (*p && *p == ' ') p++ ;
490
strcpy(nextstring, p) ;
491
nextstring += strlen(p) + 1 ;
496
ps = (struct papsiz *)mymalloc((integer)sizeof(struct papsiz)) ;
497
ps->next = papsizes ;
500
while (*p && *p > ' ')
503
ps->name = newstring(ps->name) ;
504
while (*p && *p <= ' ') p++ ;
505
handlepapersize(p, &hsiz, &vsiz) ;
508
ps->specdat = nextstring++ ;
514
dopprescan = (was_inline[1] != '0') ;
518
if (sscanf(was_inline+1, "%ld", &pagecopies) != 1)
519
bad_config("missing pagecopies to b") ;
521
if (sscanf(was_inline+1, "%d", &pagecopies) != 1)
522
bad_config("missing pagecopies to b") ;
524
if (pagecopies < 1 || pagecopies > 1000)
525
bad_config("pagecopies not between 1 and 1000") ;
529
if (sscanf(was_inline+1, "%ld", &swmem) != 1)
530
bad_config("missing swmem to m") ;
531
#else /* ~SHORTINT */
532
if (sscanf(was_inline+1, "%d", &swmem) != 1)
533
bad_config("missing swmem to m") ;
534
#endif /* ~SHORTINT */
535
swmem += fontmem ; /* grab headers we've seen already */
538
/* If the user specified a -mode, don't replace it. */
540
mfmode = configstring(was_inline+1, 0) ;
544
for (pp=mfmode; pp && *pp>' '; pp++) ;
545
if (pp && *pp == ' ') {
547
while (*pp && *pp <= ' ')
557
oname = configstring(was_inline+1, 1) ;
558
if ((*oname && oname[strlen(oname)-1] == ':')
559
|| (stat(oname, &st_buf) == 0 && S_ISCHR(st_buf.st_mode))) {
560
sendcontrolD = 1 ; /* if we send to a device, *we* are spooler */
561
#if defined(MSDOS) || defined(OS2)
562
oname[strlen(oname)-1] = 0 ;
568
sendcontrolD = (was_inline[1] != '0') ;
572
handlepapersize(p, &hoff, &voff) ;
577
char tempname[INLINE_SIZE] ;
578
extern char *fliparse() ;
579
if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config("missing arg to L") ;
581
flipath = getpath(fliparse(PSname,tempname), flipath);
582
fliname = newstring(tempname) ;
588
if (sscanf(was_inline+1, "%s", PSname) != 1)
589
bad_config("missing arg to T") ;
592
SET_CLIENT_PATH (kpse_tfm_format, PSname);
594
tfmpath = getpath(PSname, tfmpath) ;
598
if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config("missing arg to P") ;
601
SET_CLIENT_PATH (kpse_pk_format, PSname);
603
pkpath = getpath(PSname, pkpath) ;
608
while (*p && *p <= ' ')
611
if (sscanf(p+1, "%s", PSname) != 1)
612
bad_config("missing arg to p") ;
615
psmapfile = configstring(was_inline+1, 0) ;
618
case 'v' : case 'V' :
619
if (sscanf(was_inline+1, "%s", PSname) != 1)
620
bad_config("missing arg to V") ;
623
SET_CLIENT_PATH (kpse_vf_format, PSname);
625
vfpath = getpath(PSname, vfpath) ;
629
if (sscanf(was_inline+1, "%s", PSname) != 1)
630
bad_config("missing arg to S") ;
633
SET_CLIENT_PATH (kpse_pict_format, PSname);
635
figpath = getpath(PSname, figpath) ;
642
if (sscanf(was_inline+1, "%s", PSname) != 1)
643
bad_config("missing arg to H") ;
646
SET_CLIENT_PATH (headerpath, PSname);
648
headerpath = getpath(PSname, headerpath) ;
651
case '%': case ' ' : case '*' : case '#' : case ';' :
652
case '=' : case 0 : case '\n' :
655
reverse = (was_inline[1] != '0') ;
658
* This case is for last resort font scaling; I hate this, but enough
659
* people have in no uncertain terms demanded it that I'll go ahead and
662
* This line must have numbers on it, resolutions, to search for the
663
* font as a last resort, and then the font will be scaled. These
664
* resolutions should be in increasing order.
666
* For most machines, just `300' is sufficient here; on the NeXT,
667
* `300 400' may be more appropriate.
674
while (*p && *p <= ' ')
676
if ('0' <= *p && *p <= '9') {
678
while ('0' <= *p && *p <= '9')
679
j = 10 * j + (*p++ - '0') ;
681
if (lastresortsizes[i-1] > j) {
682
bad_config("last resort sizes (R) must be sorted") ;
684
lastresortsizes[i++] = j ;
688
bad_config("only numbers expected on `R' line") ;
691
lastresortsizes[i] = 32000 ;
693
for (p = was_inline + 1; *p; p++) {
698
kpse_fallback_resolutions_string = xstrdup (was_inline + 1);
702
if (sscanf(was_inline+1, "%d", &actualdpi) != 1)
703
bad_config("missing arg to D") ;
704
if (actualdpi < 10 || actualdpi > 10000)
705
bad_config("dpi must be between 10 and 10000") ;
706
vactualdpi = actualdpi;
709
* Execute a command. This can be dangerous, but can also be very useful.
713
error("dvips was compiled with SECURE, which disables E in config") ;
716
error("dvips -R option used, which disables E in config") ;
719
(void)system(was_inline+1) ;
723
removecomments = (was_inline[1] != '0') ;
726
nosmallchars = (was_inline[1] != '0') ;
729
for (p=was_inline+1; *p && *p <= ' '; p++) ;
731
warningmsg = newstring(p) ;
736
if (sscanf(was_inline+1, "%d", &actualdpi) != 1)
737
bad_config("missing numeric arg to X") ;
738
if (actualdpi < 10 || actualdpi > 10000)
739
bad_config("X arg must be between 10 and 10000") ;
742
if (sscanf(was_inline+1, "%d", &vactualdpi) != 1)
743
bad_config("missing numeric arg to Y") ;
744
if (vactualdpi < 10 || vactualdpi > 10000)
745
bad_config("Y arg must be between 10 and 10000") ;
748
if (sscanf(was_inline+1, "%lg", &mag) != 1)
749
bad_config("missing arg to x or y") ;
750
overridemag = (was_inline[0] == 'x') ? 1 : -1 ;
753
if (sscanf(was_inline+1, "%d", &maxdrift) != 1)
754
bad_config("missing arg to e") ;
755
if (maxdrift < 0) bad_config("bad argument to e") ;
756
vmaxdrift = maxdrift;
759
if (secure_option && secure && was_inline[1] == '0') {
761
"warning: %s: z0 directive ignored since -R1 given\n",
764
secure = (was_inline[1] != '0') ;
767
case 'q' : case 'Q' :
768
quiet = (was_inline[1] != '0') ;
771
filter = (was_inline[1] != '0') ;
774
/* noenv has already been tested, so no point in setting. */
779
shiftlowchars = (was_inline[1] != '0') ;
783
if (sscanf(was_inline+1, "%s", PSname) != 1)
784
bad_config("missing arg to h") ;
785
else (void)add_header(PSname) ;
788
if (sscanf(was_inline+1, "%d", &maxsecsize) != 1)
793
noenv = (was_inline[1] != '0') ;
796
disablecomments = (was_inline[1] != '0') ;
799
compressed = (was_inline[1] != '0') ;
802
partialdownload = (was_inline[1] != '0') ;
805
if (sscanf(was_inline+1, "%s", PSname) != 1)
806
bad_config("missing arg to t") ;
808
if (strcmp(PSname, "landscape") == 0) {
809
if (hpapersize || vpapersize)
811
"both landscape and papersize specified; ignoring landscape") ;
815
paperfmt = newstring(PSname) ;
819
bad_config("strange line") ;
822
(void)fclose(deffile) ;
827
sprintf (msg, "warning: no config file for `%s'", printer);
837
* If a character pointer is passed in, use that name; else, use the
838
* default (possibly set) name, psfonts.map.
840
void getpsinfo P1C(char *, name)
844
char *specinfo, *downloadinfo ;
851
if ((deffile=search(mappath, name, READ))!=NULL) {
852
while (fgets(was_inline, INLINE_SIZE, deffile)!=NULL) {
854
if (*p > ' ' && *p != '*' && *p != '#' && *p != ';' && *p != '%') {
855
char *TeXname = NULL ;
856
char *PSname = NULL ;
857
char *Fontfile = NULL;
858
char *Vectfile = NULL;
859
char *hdr_name = NULL;
860
boolean nopartial_p = false;
861
boolean encoding_p = false;
863
downloadinfo = NULL ;
868
while (*p && *p <= ' ')
871
if (*p == '"') { /* PostScript instructions? */
873
strcat(specbuf, specinfo) ;
874
strcat(specbuf, " ") ;
878
} else if (*p == '<') { /* Header to download? */
879
/* If had previous downloadinfo, save it. */
881
strcat(downbuf, downloadinfo) ;
882
strcat(downbuf, " ") ;
885
if (p[1] == '<') { /* << means always full download */
888
} else if (p[1] == '[') { /* <[ means an encoding */
893
/* skip whitespace after < */
894
while (*p && *p <= ' ')
897
/* save start of header name */
900
} else if (TeXname) /* second regular word on line? */
903
else /* first regular word? */
907
p++ ; /* find end of "..." word */
908
while (*p != '"' && *p)
911
while (*p > ' ') /* find end of anything else */
916
/* If we had a header we were downloading, figure
917
out what to do; couldn't do this above since we
918
want to check the suffix. */
920
char *suffix = find_suffix (hdr_name);
921
if (encoding_p || STREQ (suffix, "enc")) {
922
/* (SPQR) if it is a reencoding, pass on to
923
FontPart, and download as usual */
924
Vectfile = downloadinfo = hdr_name;
925
} else if (nopartial_p) {
926
downloadinfo = hdr_name ;
927
} else if (FILESTRCASEEQ (suffix, "pfa")
928
|| FILESTRCASEEQ (suffix, "pfb")
929
|| STREQ (suffix, "PFA")
930
|| STREQ (suffix, "PFB")) {
933
downloadinfo = hdr_name;
939
strcat(specbuf, specinfo) ;
941
strcat(downbuf, downloadinfo) ;
942
slen = strlen(downbuf) - 1;
943
if (downbuf[slen] == ' ') {
947
TeXname = newstring(TeXname) ;
948
PSname = newstring(PSname) ;
949
Fontfile = newstring(Fontfile);
950
Vectfile = newstring(Vectfile);
951
specinfo = newstring(specbuf) ;
952
downloadinfo = newstring(downbuf) ;
953
add_entry(TeXname, PSname, Fontfile, Vectfile,
954
specinfo, downloadinfo) ;
958
(void)fclose(deffile) ;
964
* Get environment variables! These override entries in ./config.h.
965
* We substitute everything of the form ::, ^: or :$ with default,
966
* so a user can easily build on to the existing paths.
968
static char *getenvup P2C(char *, who, char *, what)
970
return getpath(getenv(who), what) ;
973
#if !defined(KPATHSEA) && defined(SEARCH_SUBDIRECTORIES)
974
static char *concat3();
976
void checkenv P1C(int, which)
980
tfmpath = getenvup(FONTPATH, tfmpath) ;
981
vfpath = getenvup("VFFONTS", vfpath) ;
982
pictpath = getenvup("TEXPICTS", pictpath) ;
983
figpath = getenvup("TEXINPUTS", figpath) ;
984
headerpath = getenvup("DVIPSHEADERS", headerpath) ;
985
if (getenv("TEXPKS"))
986
pkpath = getenvup("TEXPKS", pkpath) ;
987
else if (getenv("TEXPACKED"))
988
pkpath = getenvup("TEXPACKED", pkpath) ;
989
else if (getenv("PKFONTS"))
990
pkpath = getenvup("PKFONTS", pkpath) ;
991
#ifdef SEARCH_SUBDIRECTORIES
992
else if (getenv(FONTPATH))
993
pkpath = getenvup(FONTPATH, pkpath) ;
994
if (getenv ("TEXFONTS_SUBDIR"))
995
fontsubdirpath = getenvup ("TEXFONTS_SUBDIR", fontsubdirpath);
998
char *do_subdir_path();
999
char *dirs = do_subdir_path (fontsubdirpath);
1000
/* If the paths were in dynamic storage before, that memory is
1002
pathsep[0] = PATHSEP ;
1004
tfmpath = concat3 (tfmpath, pathsep, dirs);
1005
pkpath = concat3 (pkpath, pathsep, dirs);
1009
configpath = getenvup("TEXCONFIG", configpath) ;
1013
#if !defined(KPATHSEA) && defined(SEARCH_SUBDIRECTORIES)
1015
#include <sys/types.h>
1016
#include <sys/stat.h>
1021
typedef struct dirent *directory_entry_type;
1023
#include <sys/dir.h>
1024
typedef struct direct *directory_entry_type;
1027
/* Declare the routine to get the current working directory. */
1030
extern char *getwd ();
1031
#define getcwd(b, len) ((b) ? getwd (b) : getwd (xmalloc (len)))
1034
extern char *getcwd (char *, int);
1036
extern char *getcwd ();
1037
#endif /* not ANSI */
1038
#endif /* not HAVE_GETWD */
1040
#if defined(SYSV) || defined(VMS) || defined(MSDOS) || defined(OS2) || defined(ATARIST)
1041
#define MAXPATHLEN (256)
1043
#include <sys/param.h> /* for MAXPATHLEN */
1046
extern void exit() ;
1047
extern int chdir() ;
1049
/* Memory operations: variants of malloc(3) and realloc(3) that just
1050
give up the ghost when they fail. */
1053
xmalloc P1C(unsigned, size)
1055
char *mem = malloc (size);
1059
fprintf (stderr, "! Cannot allocate %u bytes.\n", size);
1068
xrealloc P2C(char *, ptr, unsigned, size)
1070
char *mem = realloc (ptr, size);
1074
fprintf (stderr, "! Cannot reallocate %u bytes at %x.\n", size, (int)ptr);
1082
/* Return, in NAME, the next component of PATH, i.e., the characters up
1083
to the next PATHSEP. */
1086
next_component P2C(char *, name, char **, path)
1090
while (**path != 0 && **path != PATHSEP)
1092
name[count++] = **path;
1093
(*path)++; /* Move further along, even between calls. */
1097
if (**path == PATHSEP)
1098
(*path)++; /* Move past the delimiter. */
1102
#ifndef _POSIX_SOURCE
1104
#define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
1108
/* Return true if FN is a directory or a symlink to a directory,
1112
is_dir P1C(char *, fn)
1116
return stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode);
1121
concat3 P3C(char *, s1, char *, s2, char *, s3)
1123
char *r = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
1131
/* DIR_LIST is the default list of directories (colon-separated) to
1132
search. We want to add all the subdirectories directly below each of
1133
the directories in the path.
1135
We return the list of directories found. */
1138
do_subdir_path P1C(char *, dir_list)
1142
char *result = xmalloc ((unsigned)1);
1143
char *temp = dir_list;
1146
dirsep[0] = DIRSEP ;
1149
/* Make a copy in writable memory. */
1150
dir_list = xmalloc (strlen (temp) + 1);
1151
strcpy (dir_list, temp);
1155
/* Unfortunately, we can't look in the environment for the current
1156
directory, because if we are running under a program (let's say
1157
Emacs), the PWD variable might have been set by Emacs' parent
1158
to the current directory at the time Emacs was invoked. This
1159
is not necessarily the same directory the user expects to be
1160
in. So, we must always call getcwd(3) or getwd(3), even though
1161
they are slow and prone to hang in networked installations. */
1162
cwd = getcwd (NULL, MAXPATHLEN + 2);
1172
directory_entry_type e;
1173
char dirname[MAXPATHLEN];
1175
next_component (dirname, &dir_list);
1177
/* All the `::'s should be gone by now, but we may as well make
1178
sure `chdir' doesn't crash. */
1179
if (*dirname == 0) continue;
1181
/* By changing directories, we save a bunch of string
1182
concatenations (and make the pathnames the kernel looks up
1184
if (chdir (dirname) != 0) continue;
1186
dir = opendir (".");
1187
if (dir == NULL) continue;
1189
while ((e = readdir (dir)) != NULL)
1191
if (is_dir (e->d_name) && strcmp (e->d_name, ".") != 0
1192
&& strcmp (e->d_name, "..") != 0)
1194
char *found = concat3 (dirname, dirsep, e->d_name);
1196
result = xrealloc (result, strlen (result) + strlen (found) + 2);
1198
len = strlen (result);
1201
result[len] = PATHSEP;
1202
result[len + 1] = 0;
1204
strcat (result, found);
1210
/* Change back to the current directory, in case the path
1211
contains relative directory names. */
1212
if (chdir (cwd) != 0)
1218
while (*dir_list != 0);
1222
#endif /* SEARCH_SUBDIRECTORIES */