echo ; /* Note that this declares an int available externally failat 1 ;lc:lc -cuwsf -Heco.sym -O -v -dEXTRA eco.c ; to generate ecox ;lc:blink lib:cres.o ecox.o TO ecox LIB lib:lc.lib SD SC ND VERBOSE lc:lc -cuwsf -Heco.sym -O -v eco.c ; to generate eco lc:blink lib:cres.o eco.o TO eco LIB lib:lc.lib SD SC ND VERBOSE quit */ /* * Created on 88/10/27 Last mod: 90/04/01 * * Module: Eco by Dario de Judicibus - Rome (Italy) * * Purpose: echoes a string to the console - allowed control sequences * Created from eco. It includes \[...] escape sequences. * ECO is the Italian word for Echo. * * Syntax: eco "string" * * ParmList: string a sequence of character strings and control * sequences (CS). Escape character is backslash (\) * See eco.hlp for CS list. Execute eco.me as demo. * Double quotes are mandatory if string contains: * semicolons (;) * minor chars (<) * major chars (>) * Double quotes can be included by escape sequence \q * * Author's addresses: MAIL Dario de Judicibus * via Canton 101 * I 00144 Roma ITALIA * * E-Mail SAM Link (+39.6.423233) Userid 244 * MC Link (+39.6.4180440) MC2120 * * ========================================================================= * @Mod | on | by | reason * -----+--------+-----+---------------------------------------------------- * @001 | 871027 | DdJ | Vers 1 Rel 0 Mod 0 * @002 | 881002 | DdJ | Vers 2 Rel 0 Mod 0 - Lattice 4.0 * @003 | 881017 | DdJ | Vers 2 Rel 1 Mod 0 - \< & \> * @004 | 881027 | DdJ | Vers 3 Rel 0 Mod 0 - \[...] * @005 | 890724 | DdJ | Vers 3 Rel 1 Mod 0 - Lattice 5.02 * @006 | 890726 | DdJ | Vers 3 Rel 2 Mod 0 - \W & \D * @007 | 890916 | DdJ | Vers 3 Rel 2 Mod 1 - \{..} & fixed bug in \[..] * @008 | 891125 | DdJ | Vers 3 Rel 2 Mod 2 - Added getenv() (Lattice bug) * @009 | 900111 | DdJ | Vers 3 Rel 3 Mod 0 - pre-comp. include & resident * @010 | 900401 | DdJ | Vers 3 Rel 4 Mod 0 - New command feature */ /* ** #include lines collected in ecohdr.c and pre-compiled */ #ifdef EXTRA /* ** I had to add an internal getenv() routine because the Lattice C 5.04 ** one has a bug: the variable content is returned overlayed to the ** variable file name ENV:vatiable_name. ** #define getenv GetEnv is used to avoid a Lattice error message */ #define ENVSIZE 256 #define getenv GetEnv typedef struct FileHandle FH; char *getenv(char *); #endif void help(void); #define tohex(c) (isdigit(c)?((c)&0x0F):(((c)-('7'))&0x0F)) #ifdef EXTRA #define todigit(c) (isdigit(c)?(((c)-('0'))&0x0F):0) #endif /* Help */ #define HLP_0 "\nECO Vers. 3.40 by Dario de Judicibus - Italy\n\nEscape sequences \\:\n\n" #define HLP_1 "Special Chars: q Quotes, x__ Hex value (two digits), ? ? character\nColours: 0..3 Foreground 4..7 Background\n" #define HLP_2 "Screen: C Home and clear, c Clear to end of display\nStyles: p Plain, b Bold, i Italic, u Underscore, r Reverse, d Default\n" #define HLP_3 "Cursor: < Invisible, > Visible, H Home, (x,y) Cursor positioning\nLine control: n Newline, f Carriage Return, s no Newline at the end\n" #define HLP_4 "Tabs: v Vertical, t Horizontal\n" #ifdef EXTRA #define HLP_A "Variables: [var..var] where var = {d1..d7,t1..t7,w1..w2,p}\nDelays: W Wait for ENTER, Dx Wait for x seconds\n" #define HLP_B "Environment: {variable} where variable is an ENV: variable\n $command$ will execute the command from current CLI\n" #endif #define HLP_X "\nECO ? or ECO \\h for help, ECO \042?\042 or ECO \\? to output ? as first char in list.\n\n" /* Control Sequences Definitions */ #define ESCAPE '\\' /* Escape character */ #define ESC "\\" /* Escape character */ #define DEF "\2330;31;40m" /* Normal */ #define F_0 "\23330m" /* Foreground 0 */ #define F_1 "\23331m" /* Foreground 1 */ #define F_2 "\23332m" /* Foreground 2 */ #define F_3 "\23333m" /* Foreground 3 */ #define B_0 "\23340m" /* Background 0 */ #define B_1 "\23341m" /* Background 1 */ #define B_2 "\23342m" /* Background 2 */ #define B_3 "\23343m" /* Background 3 */ #define S_P "\2330m" /* Plain */ #define S_B "\2331m" /* Bold */ #define S_I "\2333m" /* Italic */ #define S_U "\2334m" /* Underscore */ #define S_R "\2337m" /* Reverse */ #define VT "\v" /* Vertical tab */ #define HT "\t" /* Horizontal tab */ #define CRLF "\n" /* newline */ #define CR "\x0D" /* carriage return -- first column */ #define HOME "\233H" /* home */ #define CLSALL "\233H\233J" /* home and clear screen */ #define CLS "\233J" /* clear screen */ #define CUROFF "\2330 p" /* make cursor invisible */ #define CURON "\233 p" /* make cursor visible */ #define QUOTE "\x22" #define QMARK "\x3F" #define NL '\0' #define NOVALUE (-1) #define LAST(c) ((c == '\0')||(c == '\n')) #define SKIP(c) ((c == ' ')||(c == '\t')||(c == '\n')) #define INDEX(c) ((((c)<('0'))||((c)>('~')))?NOVALUE:((c)-('0'))) BOOL nostop = FALSE; /*------------------------------------------------------------------------*\ * # -> used in table ! -> used in switch (blank) -> not used * * * * #0 #1 #2 #3 #4 #5 #6 #7 8 9 : ; #< = #> #? * * @ A B #C !D E F G #H I J K L M N O * * P Q R S T U V !W X Y Z ![ #\ ] ^ _ * * ` a #b #c #d e #f g !h #i j k l m #n o * * #p #q #r !s #t #u #v w !x y z !{ | } ~ * * * * !( !$ * \*------------------------------------------------------------------------*/ char *_table[] = { F_0, F_1, F_2, F_3, B_0, B_1, B_2, B_3, NL, NL, NL, NL, CUROFF, NL, CURON, QMARK, NL, NL, NL, CLSALL, NL, NL, NL, NL, HOME, NL, NL, NL, NL, NL, NL, NL, NL, NL, NL, NL, NL, NL, NL, NL, NL, NL, NL, NL, ESC, NL, NL, NL, NL, NL, S_B, CLS, DEF, NL, CR, NL, NL, S_I, NL, NL, NL, NL, CRLF, NL, S_P, QUOTE, S_R, NL, HT, S_U, VT, NL, NL, NL, NL, NL, NL, NL, NL /* end */ }; #ifdef EXTRA char *weekdays[] = { "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday", "SUN" ,"MON" ,"TUE" ,"WED" ,"THU" ,"FRI" ,"SAT" }; #endif /* * Format text */ void _main(line) register unsigned char *line; { BOOL inQuote; #ifdef EXTRA char *old, *temp, *env, clk[8], h[64]; #endif #ifndef EXTRA char *old, *temp, h[10]; #endif UWORD j, index; echo = Output(); if (!(line)) Exit(RETURN_WARN);/* Must be called from CLI */ while (*line != ' ') line++; /* Skip over command name */ temp = line; while (SKIP(*temp)) temp++; /* Skip over leading blanks */ if (*temp == '\0') /* End of line: do just a \n */ { Write(echo,CRLF,1); Exit(RETURN_OK); } if (*temp == '?') /* Help, only if first char */ { help(); Exit(RETURN_OK); } inQuote = (*temp == '"'); /* if the line starts with " */ line = inQuote?++temp:++line; /* take just what in quote, */ /* otherwise get all */ old = line; temp = (char *)NL; while(!LAST(*line)) { if (*line == ESCAPE) { *line = '\0'; Write(echo,old,strlen(old)); switch(*(++line)) { case 'h': help(); line++; break; case 's': temp = line; nostop = TRUE; line++; break; case '(': h[0] = '\233'; line++; for (j=1; *line != ')' && !LAST(*line); j++, line++) h[j] = (*line == ',') ? ';' : *line; h[j] = ')'; /* to be sure */ h[j++] = 'H'; h[j] = '\0'; Write(echo,h,strlen(h)); line++; break; case 'x': if (isxdigit(line[1]) && isxdigit(line[2])) { h[0] = (tohex(line[1])<<4)|tohex(line[2]); Write(echo,h,1); } line = &line[3]; break; #ifdef EXTRA case '[': for (line++;(*line != ']') && !LAST(*line);line++) { h[0] = '\0'; if (*line == 'p') { (VOID)getcd(0,&h[0]); } else if ((*(line+1) != ']') && !LAST(*(line+1))) { getclk(clk); index = 0x07&todigit(*(line+1)); if (index) switch(*line) { case 'd': (void)stpdate(h,(int)index,&clk[1]); break; case 't': (void)stptime(h,(int)index,&clk[4]); break; case 'w': index = (UWORD)clk[0] + (0x01&index)*7; (void)strcpy(h,weekdays[index]); break; default: break; } } Write(echo,h,strlen(h)); } line++; break; case '{': for (j=0,line++;(*line != '}') && !LAST(*line);j++,line++) { h[j] = *line; } h[j] = '\0'; env = getenv(&h[0]); if (env) { Write(echo,env,strlen(env)); (void)free(env); } line++; break; case '$': for (j=0,line++;(*line != '$') && !LAST(*line);j++,line++) { h[j] = *line; } h[j] = '\0'; Execute(&h[0],NULL,echo); line++; break; case 'D': if (isdigit(line[1])) { j = TICKS_PER_SECOND * todigit(line[1]); Delay(j); } line = &line[2]; break; case 'W': Read(echo,h,63); line++; break; #endif default: index = (UWORD)INDEX(*line); if ((index != NOVALUE)&&(_table[index] != NL)) Write(echo,_table[index],strlen(_table[index])); line++; } old = line; } else { if (inQuote && (*line == '"')) break; line++; } } *line = '\0'; Write(echo,old,strlen(old)); if (!(nostop && (line == ++temp))) Write(echo,CRLF,1); Exit(RETURN_OK); } #ifdef EXTRA /* ** This procedure will be deleted as soon as the Lattice one will ** be fixed. */ char *getenv(varname) char *varname; { char *p, *buf = NULL; FH *envfh; if ((buf = calloc(1,ENVSIZE)) != NULL) { p = strcpy(buf,"ENV:"); p = strcat(buf,varname); if ((envfh = (FH *)Open(buf,MODE_OLDFILE)) != NULL) { p = memset(buf,'\0',ENVSIZE); (void)Read((BPTR)envfh,buf,ENVSIZE); Close((BPTR)envfh); } else buf[0] = '\0'; } return (buf); } #endif /* ** Help */ void help() { Write(echo,HLP_0,strlen(HLP_0)); Write(echo,HLP_1,strlen(HLP_1)); Write(echo,HLP_2,strlen(HLP_2)); Write(echo,HLP_3,strlen(HLP_3)); Write(echo,HLP_4,strlen(HLP_4)); #ifdef EXTRA Write(echo,HLP_A,strlen(HLP_A)); Write(echo,HLP_B,strlen(HLP_B)); #endif Write(echo,HLP_X,strlen(HLP_X)); }