1c80476e4SDavid E. O'Brien /*
2c80476e4SDavid E. O'Brien * tw.color.c: builtin color ls-F
3c80476e4SDavid E. O'Brien */
4c80476e4SDavid E. O'Brien /*-
5c80476e4SDavid E. O'Brien * Copyright (c) 1998 The Regents of the University of California.
6c80476e4SDavid E. O'Brien * All rights reserved.
7c80476e4SDavid E. O'Brien *
8c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without
9c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions
10c80476e4SDavid E. O'Brien * are met:
11c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright
12c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer.
13c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright
14c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the
15c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution.
1629301572SMark Peek * 3. Neither the name of the University nor the names of its contributors
17c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software
18c80476e4SDavid E. O'Brien * without specific prior written permission.
19c80476e4SDavid E. O'Brien *
20c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30c80476e4SDavid E. O'Brien * SUCH DAMAGE.
31c80476e4SDavid E. O'Brien */
32c80476e4SDavid E. O'Brien #include "sh.h"
33c80476e4SDavid E. O'Brien #include "tw.h"
34c80476e4SDavid E. O'Brien #include "ed.h"
35c80476e4SDavid E. O'Brien #include "tc.h"
36c80476e4SDavid E. O'Brien
37c80476e4SDavid E. O'Brien #ifdef COLOR_LS_F
38c80476e4SDavid E. O'Brien
39c80476e4SDavid E. O'Brien typedef struct {
4023338178SMark Peek const char *s;
4145e5710bSMark Peek size_t len;
42c80476e4SDavid E. O'Brien } Str;
43c80476e4SDavid E. O'Brien
44c80476e4SDavid E. O'Brien
45c80476e4SDavid E. O'Brien #define VAR(suffix,variable,defaultcolor) \
46c80476e4SDavid E. O'Brien { \
47c80476e4SDavid E. O'Brien suffix, variable, { defaultcolor, sizeof(defaultcolor) - 1 }, \
48c80476e4SDavid E. O'Brien { defaultcolor, sizeof(defaultcolor) - 1 } \
49c80476e4SDavid E. O'Brien }
50c80476e4SDavid E. O'Brien #define NOS '\0' /* no suffix */
51c80476e4SDavid E. O'Brien
52c80476e4SDavid E. O'Brien typedef struct {
53c80476e4SDavid E. O'Brien const char suffix;
54c80476e4SDavid E. O'Brien const char *variable;
55c80476e4SDavid E. O'Brien Str color;
56c80476e4SDavid E. O'Brien Str defaultcolor;
57c80476e4SDavid E. O'Brien } Variable;
58c80476e4SDavid E. O'Brien
59c80476e4SDavid E. O'Brien static Variable variables[] = {
60c80476e4SDavid E. O'Brien VAR('/', "di", "01;34"), /* Directory */
61c80476e4SDavid E. O'Brien VAR('@', "ln", "01;36"), /* Symbolic link */
62c80476e4SDavid E. O'Brien VAR('&', "or", ""), /* Orphanned symbolic link (defaults to ln) */
63c80476e4SDavid E. O'Brien VAR('|', "pi", "33"), /* Named pipe (FIFO) */
64c80476e4SDavid E. O'Brien VAR('=', "so", "01;35"), /* Socket */
656767bd61SMark Peek VAR('>', "do", "01;35"), /* Door (solaris fast ipc mechanism) */
66c80476e4SDavid E. O'Brien VAR('#', "bd", "01;33"), /* Block device */
67c80476e4SDavid E. O'Brien VAR('%', "cd", "01;33"), /* Character device */
68c80476e4SDavid E. O'Brien VAR('*', "ex", "01;32"), /* Executable file */
69c80476e4SDavid E. O'Brien VAR(NOS, "fi", "0"), /* Regular file */
70c80476e4SDavid E. O'Brien VAR(NOS, "no", "0"), /* Normal (non-filename) text */
71c80476e4SDavid E. O'Brien VAR(NOS, "mi", ""), /* Missing file (defaults to fi) */
723b6eaa7bSAndrey A. Chernov #ifdef IS_ASCII
733b6eaa7bSAndrey A. Chernov VAR(NOS, "lc", "\033["), /* Left code (ASCII) */
743b6eaa7bSAndrey A. Chernov #else
75c80476e4SDavid E. O'Brien VAR(NOS, "lc", "\x27["), /* Left code (EBCDIC)*/
763b6eaa7bSAndrey A. Chernov #endif
77c80476e4SDavid E. O'Brien VAR(NOS, "rc", "m"), /* Right code */
78c80476e4SDavid E. O'Brien VAR(NOS, "ec", ""), /* End code (replaces lc+no+rc) */
7945e5710bSMark Peek VAR(NOS, "su", ""), /* Setuid file (u+s) */
8045e5710bSMark Peek VAR(NOS, "sg", ""), /* Setgid file (g+s) */
8145e5710bSMark Peek VAR(NOS, "tw", ""), /* Sticky and other writable dir (+t,o+w) */
8245e5710bSMark Peek VAR(NOS, "ow", ""), /* Other writable dir (o+w) but not sticky */
8345e5710bSMark Peek VAR(NOS, "st", ""), /* Sticky dir (+t) but not other writable */
84a15e6f9aSMark Peek VAR(NOS, "rs", "0"), /* Reset to normal color */
859ccc37e3SMark Peek VAR(NOS, "hl", "44;37"), /* Reg file extra hard links, obsolete? */
869ccc37e3SMark Peek VAR(NOS, "mh", "44;37"), /* Reg file extra hard links */
879ccc37e3SMark Peek VAR(NOS, "ca", "30;41"), /* File with capability */
88c80476e4SDavid E. O'Brien };
89c80476e4SDavid E. O'Brien
9019d2e3deSDmitry Chagin #define nvariables (sizeof(variables)/sizeof(variables[0]))
9119d2e3deSDmitry Chagin
92c80476e4SDavid E. O'Brien enum FileType {
936767bd61SMark Peek VDir, VSym, VOrph, VPipe, VSock, VDoor, VBlock, VChr, VExe,
9419d2e3deSDmitry Chagin VFile, VNormal, VMiss, VLeft, VRight, VEnd, VSuid, VSgid, VSticky,
9519d2e3deSDmitry Chagin VOther, Vstird, VReset, Vhard, Vhard2, VCap
96c80476e4SDavid E. O'Brien };
97c80476e4SDavid E. O'Brien
9819d2e3deSDmitry Chagin /*
9919d2e3deSDmitry Chagin * Map from LSCOLORS entry index to Variable array index
10019d2e3deSDmitry Chagin */
10119d2e3deSDmitry Chagin static const uint8_t map[] = {
10219d2e3deSDmitry Chagin VDir, /* Directory */
10319d2e3deSDmitry Chagin VSym, /* Symbolic Link */
10419d2e3deSDmitry Chagin VSock, /* Socket */
10519d2e3deSDmitry Chagin VPipe, /* Named Pipe */
10619d2e3deSDmitry Chagin VExe, /* Executable */
10719d2e3deSDmitry Chagin VBlock, /* Block Special */
10819d2e3deSDmitry Chagin VChr, /* Character Special */
10919d2e3deSDmitry Chagin VSuid, /* Setuid Executable */
11019d2e3deSDmitry Chagin VSgid, /* Setgid Executable */
11119d2e3deSDmitry Chagin VSticky, /* Directory writable to others and sticky */
11219d2e3deSDmitry Chagin VOther, /* Directory writable to others but not sticky */
11319d2e3deSDmitry Chagin };
11419d2e3deSDmitry Chagin
11519d2e3deSDmitry Chagin
11619d2e3deSDmitry Chagin
11719d2e3deSDmitry Chagin enum ansi {
11819d2e3deSDmitry Chagin ANSI_RESET_ON = 0, /* reset colors/styles (white on black) */
11919d2e3deSDmitry Chagin ANSI_BOLD_ON = 1, /* bold on */
12019d2e3deSDmitry Chagin ANSI_ITALICS_ON = 3, /* italics on */
12119d2e3deSDmitry Chagin ANSI_UNDERLINE_ON = 4, /* underline on */
12219d2e3deSDmitry Chagin ANSI_INVERSE_ON = 7, /* inverse on */
12319d2e3deSDmitry Chagin ANSI_STRIKETHROUGH_ON = 9, /* strikethrough on */
12419d2e3deSDmitry Chagin ANSI_BOLD_OFF = 21, /* bold off */
12519d2e3deSDmitry Chagin ANSI_ITALICS_OFF = 23, /* italics off */
12619d2e3deSDmitry Chagin ANSI_UNDERLINE_OFF = 24, /* underline off */
12719d2e3deSDmitry Chagin ANSI_INVERSE_OFF = 27, /* inverse off */
12819d2e3deSDmitry Chagin ANSI_STRIKETHROUGH_OFF = 29,/* strikethrough off */
12919d2e3deSDmitry Chagin ANSI_FG_BLACK = 30, /* fg black */
13019d2e3deSDmitry Chagin ANSI_FG_RED = 31, /* fg red */
13119d2e3deSDmitry Chagin ANSI_FG_GREEN = 32, /* fg green */
13219d2e3deSDmitry Chagin ANSI_FG_YELLOW = 33, /* fg yellow */
13319d2e3deSDmitry Chagin ANSI_FG_BLUE = 34, /* fg blue */
13419d2e3deSDmitry Chagin ANSI_FG_MAGENTA = 35, /* fg magenta */
13519d2e3deSDmitry Chagin ANSI_FG_CYAN = 36, /* fg cyan */
13619d2e3deSDmitry Chagin ANSI_FG_WHITE = 37, /* fg white */
13719d2e3deSDmitry Chagin ANSI_FG_DEFAULT = 39, /* fg default (white) */
13819d2e3deSDmitry Chagin ANSI_BG_BLACK = 40, /* bg black */
13919d2e3deSDmitry Chagin ANSI_BG_RED = 41, /* bg red */
14019d2e3deSDmitry Chagin ANSI_BG_GREEN = 42, /* bg green */
14119d2e3deSDmitry Chagin ANSI_BG_YELLOW = 43, /* bg yellow */
14219d2e3deSDmitry Chagin ANSI_BG_BLUE = 44, /* bg blue */
14319d2e3deSDmitry Chagin ANSI_BG_MAGENTA = 45, /* bg magenta */
14419d2e3deSDmitry Chagin ANSI_BG_CYAN = 46, /* bg cyan */
14519d2e3deSDmitry Chagin ANSI_BG_WHITE = 47, /* bg white */
14619d2e3deSDmitry Chagin ANSI_BG_DEFAULT = 49, /* bg default (black) */
14719d2e3deSDmitry Chagin };
14819d2e3deSDmitry Chagin #define TCSH_BOLD 0x80
149c80476e4SDavid E. O'Brien
150c80476e4SDavid E. O'Brien typedef struct {
151c80476e4SDavid E. O'Brien Str extension; /* file extension */
152c80476e4SDavid E. O'Brien Str color; /* color string */
153c80476e4SDavid E. O'Brien } Extension;
154c80476e4SDavid E. O'Brien
155c80476e4SDavid E. O'Brien static Extension *extensions = NULL;
15623338178SMark Peek static size_t nextensions = 0;
157c80476e4SDavid E. O'Brien
158c80476e4SDavid E. O'Brien static char *colors = NULL;
15923338178SMark Peek int color_context_ls = FALSE; /* do colored ls */
16023338178SMark Peek static int color_context_lsmF = FALSE; /* do colored ls-F */
161c80476e4SDavid E. O'Brien
16245e5710bSMark Peek static int getstring (char **, const Char **, Str *, int);
16345e5710bSMark Peek static void put_color (const Str *);
16445e5710bSMark Peek static void print_color (const Char *, size_t, Char);
165c80476e4SDavid E. O'Brien
166c80476e4SDavid E. O'Brien /* set_color_context():
167c80476e4SDavid E. O'Brien */
168c80476e4SDavid E. O'Brien void
set_color_context(void)16945e5710bSMark Peek set_color_context(void)
170c80476e4SDavid E. O'Brien {
171c80476e4SDavid E. O'Brien struct varent *vp = adrof(STRcolor);
172c80476e4SDavid E. O'Brien
17329301572SMark Peek if (vp == NULL || vp->vec == NULL) {
174c80476e4SDavid E. O'Brien color_context_ls = FALSE;
175c80476e4SDavid E. O'Brien color_context_lsmF = FALSE;
17629301572SMark Peek } else if (!vp->vec[0] || vp->vec[0][0] == '\0') {
177c80476e4SDavid E. O'Brien color_context_ls = TRUE;
178c80476e4SDavid E. O'Brien color_context_lsmF = TRUE;
17929301572SMark Peek } else {
180c80476e4SDavid E. O'Brien size_t i;
181c80476e4SDavid E. O'Brien
182c80476e4SDavid E. O'Brien color_context_ls = FALSE;
183c80476e4SDavid E. O'Brien color_context_lsmF = FALSE;
184c80476e4SDavid E. O'Brien for (i = 0; vp->vec[i]; i++)
185c80476e4SDavid E. O'Brien if (Strcmp(vp->vec[i], STRls) == 0)
186c80476e4SDavid E. O'Brien color_context_ls = TRUE;
187c80476e4SDavid E. O'Brien else if (Strcmp(vp->vec[i], STRlsmF) == 0)
188c80476e4SDavid E. O'Brien color_context_lsmF = TRUE;
189c80476e4SDavid E. O'Brien }
190c80476e4SDavid E. O'Brien }
191c80476e4SDavid E. O'Brien
192c80476e4SDavid E. O'Brien
193c80476e4SDavid E. O'Brien /* getstring():
194c80476e4SDavid E. O'Brien */
19523338178SMark Peek static int
getstring(char ** dp,const Char ** sp,Str * pd,int f)19645e5710bSMark Peek getstring(char **dp, const Char **sp, Str *pd, int f)
197c80476e4SDavid E. O'Brien {
198c80476e4SDavid E. O'Brien const Char *s = *sp;
199c80476e4SDavid E. O'Brien char *d = *dp;
20023338178SMark Peek eChar sc;
201c80476e4SDavid E. O'Brien
20223338178SMark Peek while (*s && (*s & CHAR) != (Char)f && (*s & CHAR) != ':') {
203c80476e4SDavid E. O'Brien if ((*s & CHAR) == '\\' || (*s & CHAR) == '^') {
20423338178SMark Peek if ((sc = parseescape(&s)) == CHAR_ERR)
205c80476e4SDavid E. O'Brien return 0;
206c80476e4SDavid E. O'Brien }
207c80476e4SDavid E. O'Brien else
20823338178SMark Peek sc = *s++ & CHAR;
20923338178SMark Peek d += one_wctomb(d, sc);
210c80476e4SDavid E. O'Brien }
211c80476e4SDavid E. O'Brien
212c80476e4SDavid E. O'Brien pd->s = *dp;
21345e5710bSMark Peek pd->len = d - *dp;
214c80476e4SDavid E. O'Brien *sp = s;
215c80476e4SDavid E. O'Brien *dp = d;
21623338178SMark Peek return *s == (Char)f;
217c80476e4SDavid E. O'Brien }
218c80476e4SDavid E. O'Brien
21919d2e3deSDmitry Chagin static void
init(size_t colorlen,size_t extnum)22019d2e3deSDmitry Chagin init(size_t colorlen, size_t extnum)
22119d2e3deSDmitry Chagin {
22219d2e3deSDmitry Chagin size_t i;
22319d2e3deSDmitry Chagin
22419d2e3deSDmitry Chagin xfree(extensions);
22519d2e3deSDmitry Chagin for (i = 0; i < nvariables; i++)
22619d2e3deSDmitry Chagin variables[i].color = variables[i].defaultcolor;
22719d2e3deSDmitry Chagin if (colorlen == 0 && extnum == 0) {
22819d2e3deSDmitry Chagin extensions = NULL;
22919d2e3deSDmitry Chagin colors = NULL;
23019d2e3deSDmitry Chagin } else {
23119d2e3deSDmitry Chagin extensions = xmalloc(colorlen + extnum * sizeof(*extensions));
23219d2e3deSDmitry Chagin colors = extnum * sizeof(*extensions) + (char *)extensions;
23319d2e3deSDmitry Chagin }
23419d2e3deSDmitry Chagin nextensions = 0;
23519d2e3deSDmitry Chagin }
23619d2e3deSDmitry Chagin
23719d2e3deSDmitry Chagin static int
color(Char x)23819d2e3deSDmitry Chagin color(Char x)
23919d2e3deSDmitry Chagin {
24019d2e3deSDmitry Chagin static const char ccolors[] = "abcdefghx";
24119d2e3deSDmitry Chagin char *p;
24219d2e3deSDmitry Chagin if (Isupper(x)) {
24319d2e3deSDmitry Chagin x = Tolower(x);
24419d2e3deSDmitry Chagin }
24519d2e3deSDmitry Chagin
24619d2e3deSDmitry Chagin if (x == '\0' || (p = strchr(ccolors, x)) == NULL)
24719d2e3deSDmitry Chagin return -1;
24819d2e3deSDmitry Chagin return 30 + (p - ccolors);
24919d2e3deSDmitry Chagin }
25019d2e3deSDmitry Chagin
25119d2e3deSDmitry Chagin static void
makecolor(char ** c,int fg,int bg,Str * v)25219d2e3deSDmitry Chagin makecolor(char **c, int fg, int bg, Str *v)
25319d2e3deSDmitry Chagin {
25419d2e3deSDmitry Chagin int l;
255*6560ac57SDmitry Chagin if (fg & 0x80) {
25619d2e3deSDmitry Chagin l = xsnprintf(*c, 12, "%.2d;%.2d;%.2d;%.2d", ANSI_BOLD_ON,
25719d2e3deSDmitry Chagin fg & ~TCSH_BOLD, (10 + bg) & ~TCSH_BOLD, ANSI_BOLD_OFF);
258*6560ac57SDmitry Chagin } else {
25919d2e3deSDmitry Chagin l = xsnprintf(*c, 6, "%.2d;%.2d",
26019d2e3deSDmitry Chagin fg & ~TCSH_BOLD, (10 + bg) & ~TCSH_BOLD);
261*6560ac57SDmitry Chagin }
26219d2e3deSDmitry Chagin
26319d2e3deSDmitry Chagin v->s = *c;
26419d2e3deSDmitry Chagin v->len = l;
26519d2e3deSDmitry Chagin *c += l + 1;
26619d2e3deSDmitry Chagin }
26719d2e3deSDmitry Chagin
26819d2e3deSDmitry Chagin /* parseLSCOLORS():
26919d2e3deSDmitry Chagin * Parse the LSCOLORS environment variable
27019d2e3deSDmitry Chagin */
27119d2e3deSDmitry Chagin static const Char *xv; /* setjmp clobbering */
27219d2e3deSDmitry Chagin void
parseLSCOLORS(const Char * value)27319d2e3deSDmitry Chagin parseLSCOLORS(const Char *value)
27419d2e3deSDmitry Chagin {
27519d2e3deSDmitry Chagin size_t i, len, clen;
27619d2e3deSDmitry Chagin jmp_buf_t osetexit;
27719d2e3deSDmitry Chagin size_t omark;
27819d2e3deSDmitry Chagin xv = value;
27919d2e3deSDmitry Chagin
28019d2e3deSDmitry Chagin if (xv == NULL) {
28119d2e3deSDmitry Chagin init(0, 0);
28219d2e3deSDmitry Chagin return;
28319d2e3deSDmitry Chagin }
28419d2e3deSDmitry Chagin
28519d2e3deSDmitry Chagin len = Strlen(xv);
28619d2e3deSDmitry Chagin len >>= 1;
28719d2e3deSDmitry Chagin clen = len * 12; /* "??;??;??;??\0" */
28819d2e3deSDmitry Chagin init(clen, 0);
28919d2e3deSDmitry Chagin
29019d2e3deSDmitry Chagin /* Prevent from crashing if unknown parameters are given. */
29119d2e3deSDmitry Chagin omark = cleanup_push_mark();
29219d2e3deSDmitry Chagin getexit(osetexit);
29319d2e3deSDmitry Chagin
29419d2e3deSDmitry Chagin /* init pointers */
29519d2e3deSDmitry Chagin
29619d2e3deSDmitry Chagin if (setexit() == 0) {
29719d2e3deSDmitry Chagin const Char *v = xv;
29819d2e3deSDmitry Chagin char *c = colors;
29919d2e3deSDmitry Chagin
30019d2e3deSDmitry Chagin int fg, bg;
30119d2e3deSDmitry Chagin for (i = 0; i < len; i++) {
30219d2e3deSDmitry Chagin fg = color(*v++);
30319d2e3deSDmitry Chagin if (fg == -1)
30419d2e3deSDmitry Chagin stderror(ERR_BADCOLORVAR, v[-1], '?');
30519d2e3deSDmitry Chagin
30619d2e3deSDmitry Chagin bg = color(*v++);
30719d2e3deSDmitry Chagin if (bg == -1)
30819d2e3deSDmitry Chagin stderror(ERR_BADCOLORVAR, '?', v[-1]);
30919d2e3deSDmitry Chagin makecolor(&c, fg, bg, &variables[map[i]].color);
31019d2e3deSDmitry Chagin }
31119d2e3deSDmitry Chagin
31219d2e3deSDmitry Chagin }
31319d2e3deSDmitry Chagin cleanup_pop_mark(omark);
31419d2e3deSDmitry Chagin resexit(osetexit);
31519d2e3deSDmitry Chagin }
316c80476e4SDavid E. O'Brien
317c80476e4SDavid E. O'Brien /* parseLS_COLORS():
318c80476e4SDavid E. O'Brien * Parse the LS_COLORS environment variable
319c80476e4SDavid E. O'Brien */
320c80476e4SDavid E. O'Brien void
parseLS_COLORS(const Char * value)32145e5710bSMark Peek parseLS_COLORS(const Char *value)
322c80476e4SDavid E. O'Brien {
32323338178SMark Peek size_t i, len;
324c80476e4SDavid E. O'Brien const Char *v; /* pointer in value */
325c80476e4SDavid E. O'Brien char *c; /* pointer in colors */
32623338178SMark Peek Extension *volatile e; /* pointer in extensions */
3278e66bd9eSDavid E. O'Brien jmp_buf_t osetexit;
32845e5710bSMark Peek size_t omark;
329c80476e4SDavid E. O'Brien
33029301572SMark Peek (void) &e;
33129301572SMark Peek
332c80476e4SDavid E. O'Brien
33319d2e3deSDmitry Chagin if (value == NULL) {
33419d2e3deSDmitry Chagin init(0, 0);
335c80476e4SDavid E. O'Brien return;
33619d2e3deSDmitry Chagin }
337c80476e4SDavid E. O'Brien
338c80476e4SDavid E. O'Brien len = Strlen(value);
339c80476e4SDavid E. O'Brien /* allocate memory */
340c80476e4SDavid E. O'Brien i = 1;
341c80476e4SDavid E. O'Brien for (v = value; *v; v++)
342c80476e4SDavid E. O'Brien if ((*v & CHAR) == ':')
343c80476e4SDavid E. O'Brien i++;
34419d2e3deSDmitry Chagin
34519d2e3deSDmitry Chagin init(len, i);
346c80476e4SDavid E. O'Brien
347c80476e4SDavid E. O'Brien /* init pointers */
348c80476e4SDavid E. O'Brien v = value;
349c80476e4SDavid E. O'Brien c = colors;
35019d2e3deSDmitry Chagin e = extensions;
351c80476e4SDavid E. O'Brien
3528e66bd9eSDavid E. O'Brien /* Prevent from crashing if unknown parameters are given. */
3538e66bd9eSDavid E. O'Brien
35445e5710bSMark Peek omark = cleanup_push_mark();
3558e66bd9eSDavid E. O'Brien getexit(osetexit);
3568e66bd9eSDavid E. O'Brien
3578e66bd9eSDavid E. O'Brien if (setexit() == 0) {
3588e66bd9eSDavid E. O'Brien
359c80476e4SDavid E. O'Brien /* parse */
360c80476e4SDavid E. O'Brien while (*v) {
361c80476e4SDavid E. O'Brien switch (*v & CHAR) {
362c80476e4SDavid E. O'Brien case ':':
363c80476e4SDavid E. O'Brien v++;
364c80476e4SDavid E. O'Brien continue;
365c80476e4SDavid E. O'Brien
366c80476e4SDavid E. O'Brien case '*': /* :*ext=color: */
367c80476e4SDavid E. O'Brien v++;
368c80476e4SDavid E. O'Brien if (getstring(&c, &v, &e->extension, '=') &&
369c80476e4SDavid E. O'Brien 0 < e->extension.len) {
370c80476e4SDavid E. O'Brien v++;
371c80476e4SDavid E. O'Brien getstring(&c, &v, &e->color, ':');
372c80476e4SDavid E. O'Brien e++;
373c80476e4SDavid E. O'Brien continue;
374c80476e4SDavid E. O'Brien }
375c80476e4SDavid E. O'Brien break;
376c80476e4SDavid E. O'Brien
377c80476e4SDavid E. O'Brien default: /* :vl=color: */
378c80476e4SDavid E. O'Brien if (v[0] && v[1] && (v[2] & CHAR) == '=') {
379c80476e4SDavid E. O'Brien for (i = 0; i < nvariables; i++)
38023338178SMark Peek if ((Char)variables[i].variable[0] == (v[0] & CHAR) &&
38123338178SMark Peek (Char)variables[i].variable[1] == (v[1] & CHAR))
382c80476e4SDavid E. O'Brien break;
383c80476e4SDavid E. O'Brien if (i < nvariables) {
384c80476e4SDavid E. O'Brien v += 3;
385c80476e4SDavid E. O'Brien getstring(&c, &v, &variables[i].color, ':');
386c80476e4SDavid E. O'Brien continue;
387c80476e4SDavid E. O'Brien }
388c80476e4SDavid E. O'Brien else
389c80476e4SDavid E. O'Brien stderror(ERR_BADCOLORVAR, v[0], v[1]);
390c80476e4SDavid E. O'Brien }
391c80476e4SDavid E. O'Brien break;
392c80476e4SDavid E. O'Brien }
393c80476e4SDavid E. O'Brien while (*v && (*v & CHAR) != ':')
394c80476e4SDavid E. O'Brien v++;
395c80476e4SDavid E. O'Brien }
3968e66bd9eSDavid E. O'Brien }
3978e66bd9eSDavid E. O'Brien
39845e5710bSMark Peek cleanup_pop_mark(omark);
3998e66bd9eSDavid E. O'Brien resexit(osetexit);
400c80476e4SDavid E. O'Brien
40145e5710bSMark Peek nextensions = e - extensions;
402c80476e4SDavid E. O'Brien }
403c80476e4SDavid E. O'Brien
404c80476e4SDavid E. O'Brien /* put_color():
405c80476e4SDavid E. O'Brien */
406c80476e4SDavid E. O'Brien static void
put_color(const Str * colorp)40719d2e3deSDmitry Chagin put_color(const Str *colorp)
408c80476e4SDavid E. O'Brien {
409c80476e4SDavid E. O'Brien size_t i;
41019d2e3deSDmitry Chagin const char *c = colorp->s;
41123338178SMark Peek int original_output_raw = output_raw;
412c80476e4SDavid E. O'Brien
413c80476e4SDavid E. O'Brien output_raw = TRUE;
41445e5710bSMark Peek cleanup_push(&original_output_raw, output_raw_restore);
41519d2e3deSDmitry Chagin for (i = colorp->len; 0 < i; i--)
416c80476e4SDavid E. O'Brien xputchar(*c++);
41745e5710bSMark Peek cleanup_until(&original_output_raw);
418c80476e4SDavid E. O'Brien }
419c80476e4SDavid E. O'Brien
420c80476e4SDavid E. O'Brien
421c80476e4SDavid E. O'Brien /* print_color():
422c80476e4SDavid E. O'Brien */
423c80476e4SDavid E. O'Brien static void
print_color(const Char * fname,size_t len,Char suffix)42445e5710bSMark Peek print_color(const Char *fname, size_t len, Char suffix)
425c80476e4SDavid E. O'Brien {
42623338178SMark Peek size_t i;
427c80476e4SDavid E. O'Brien char *filename = short2str(fname);
428c80476e4SDavid E. O'Brien char *last = filename + len;
42919d2e3deSDmitry Chagin Str *colorp = &variables[VFile].color;
430c80476e4SDavid E. O'Brien
431c80476e4SDavid E. O'Brien switch (suffix) {
432c80476e4SDavid E. O'Brien case '>': /* File is a symbolic link pointing to
433c80476e4SDavid E. O'Brien * a directory */
43419d2e3deSDmitry Chagin colorp = &variables[VDir].color;
435c80476e4SDavid E. O'Brien break;
436c80476e4SDavid E. O'Brien case '+': /* File is a hidden directory [aix] or
437c80476e4SDavid E. O'Brien * context dependent [hpux] */
438c80476e4SDavid E. O'Brien case ':': /* File is network special [hpux] */
439c80476e4SDavid E. O'Brien break;
440c80476e4SDavid E. O'Brien default:
441c80476e4SDavid E. O'Brien for (i = 0; i < nvariables; i++)
442c80476e4SDavid E. O'Brien if (variables[i].suffix != NOS &&
44323338178SMark Peek (Char)variables[i].suffix == suffix) {
44419d2e3deSDmitry Chagin colorp = &variables[i].color;
445c80476e4SDavid E. O'Brien break;
446c80476e4SDavid E. O'Brien }
447c80476e4SDavid E. O'Brien if (i == nvariables) {
448c80476e4SDavid E. O'Brien for (i = 0; i < nextensions; i++)
44945e5710bSMark Peek if (len >= extensions[i].extension.len
45045e5710bSMark Peek && strncmp(last - extensions[i].extension.len,
451c80476e4SDavid E. O'Brien extensions[i].extension.s,
452c80476e4SDavid E. O'Brien extensions[i].extension.len) == 0) {
45319d2e3deSDmitry Chagin colorp = &extensions[i].color;
454c80476e4SDavid E. O'Brien break;
455c80476e4SDavid E. O'Brien }
456c80476e4SDavid E. O'Brien }
457c80476e4SDavid E. O'Brien break;
458c80476e4SDavid E. O'Brien }
459c80476e4SDavid E. O'Brien
460c80476e4SDavid E. O'Brien put_color(&variables[VLeft].color);
46119d2e3deSDmitry Chagin put_color(colorp);
462c80476e4SDavid E. O'Brien put_color(&variables[VRight].color);
463c80476e4SDavid E. O'Brien }
464c80476e4SDavid E. O'Brien
465c80476e4SDavid E. O'Brien
466c80476e4SDavid E. O'Brien /* print_with_color():
467c80476e4SDavid E. O'Brien */
468c80476e4SDavid E. O'Brien void
print_with_color(const Char * filename,size_t len,Char suffix)46945e5710bSMark Peek print_with_color(const Char *filename, size_t len, Char suffix)
470c80476e4SDavid E. O'Brien {
471c80476e4SDavid E. O'Brien if (color_context_lsmF &&
472c80476e4SDavid E. O'Brien (haderr ? (didfds ? is2atty : isdiagatty) :
473c80476e4SDavid E. O'Brien (didfds ? is1atty : isoutatty))) {
474c80476e4SDavid E. O'Brien print_color(filename, len, suffix);
475c80476e4SDavid E. O'Brien xprintf("%S", filename);
476c80476e4SDavid E. O'Brien if (0 < variables[VEnd].color.len)
477c80476e4SDavid E. O'Brien put_color(&variables[VEnd].color);
478c80476e4SDavid E. O'Brien else {
479c80476e4SDavid E. O'Brien put_color(&variables[VLeft].color);
480c80476e4SDavid E. O'Brien put_color(&variables[VNormal].color);
481c80476e4SDavid E. O'Brien put_color(&variables[VRight].color);
482c80476e4SDavid E. O'Brien }
483c80476e4SDavid E. O'Brien }
484c80476e4SDavid E. O'Brien else
48523338178SMark Peek xprintf("%S", filename);
48623338178SMark Peek xputwchar(suffix);
487c80476e4SDavid E. O'Brien }
488c80476e4SDavid E. O'Brien
489c80476e4SDavid E. O'Brien
490c80476e4SDavid E. O'Brien #endif /* COLOR_LS_F */
491