Category : Recently Uploaded Files
Archive   : BATCSH11.ZIP
Filename : BAT2CSH.L

 
Output of file : BAT2CSH.L contained in archive : BATCSH11.ZIP

%option noyywrap
%{
/**************************************************************************/
/* MODULE: bat2csh.l */
/* PURPOSE: converts dos batch files to unix csh files */
/* AUTHOR: Bill Pierpoint */
/* LEX: FLEX Version 2.5.1 */
/* COMPILER: Borland C Version 3.1 */
/* COPYRIGHT: None. Public Domain. */
/* VERSION: 1.10 */
/* RELEASE: May 23, 1995 */
/**************************************************************************/
/* HISTORY:

05/23/95 - v. 1.10
Moved '<' and '>' characters from legal to delim for better handling
of redirection. Improved path specifier code in cvt_token function.
Added attrib to chmod translation.

01/12/94 - v. 1.00
Initial public release.
*/

#include
#ifdef __BORLANDC__
#pragma hdrstop
#endif

#define putstr(s) fputs((s), stdout)
#define puttab() fputc('\t', stdout)
#define putln() fputc('\n', stdout)
#define token(t) (t)
#define ckeol(t) do { if((t)==EOL) { puts(" ### SYNTAX ERROR ###"); \
errorcount++; return;} } while(0)
#define cktok(t, x) do { if((t)!=(x)) { puts(" ### SYNTAX ERROR ###"); \
errorcount++; eattokens(); return;} } while(0)

typedef struct
{
int token;
void (*fn)(void);
} FNTBL;

#define STRBUFSIZE 257
char textbuf[STRBUFSIZE];

/**************************************************************************/
/* token enumeration */
/**************************************************************************/
enum {
OTHER=1,
EOL,
SPACE,
VARIABLE,
PARAMETER,
WORD,
INIT_CALL,
INIT_ECHO,
INIT_FOR,
INIT_GOTO,
INIT_IF,
INIT_PATH,
INIT_PAUSE,
INIT_REM,
INIT_SET,
INIT_SHIFT,
INIT_LABEL,
INIT_COMMAND,
ECHO_ON,
ECHO_OFF,
ECHO_DOT,
IF_NOT,
IF_ERRORLEVEL,
IF_EXIST,
FOR_VARIABLE,
FOR_IN,
FOR_WORDLIST,
FOR_DO
};

/**************************************************************************/
/* function prototypes */
/**************************************************************************/
/* support functions */
char *cvt_parameter(char *s);
char *cvt_variable(char *s);
char *cvt_for_variable(char *s);
char *cvt_set_variable(int token);
char *cvt_token(int token, char *s);
int dispatch(void);
void indent(void);
int lex(void);
void putbacktoken(void);
void puttokln(int token, char *start, char *end);
int reporterrors(void);
void terminate(void);
char *tr(char *s, int oldch, int newch);

/* keyword functions */
void kw_call(void);
void kw_command(void);
void kw_echo(void);
void kw_for(void);
void kw_goto(void);
void kw_if(void);
void kw_label(void);
void kw_ln(void);
void kw_path(void);
void kw_pause(void);
void kw_remark(void);
void kw_set(void);
void kw_shift(void);

%}

digit [0-9]
delim [ \t=;<>]
name [-{}()&#!~$a-zA-Z0-9]
legal [!-$&-:?-~]
other .

%x ECHOS
%x TEXT
%x FOR

%%
^"@" ;
call return token(INIT_CALL);
echo return token(INIT_ECHO);
for return token(INIT_FOR);
goto return token(INIT_GOTO);
if return token(INIT_IF);
pause return token(INIT_PAUSE);
rem return token(INIT_REM);
set return token(INIT_SET);
path return token(INIT_PATH);
shift return token(INIT_SHIFT);
^":"{name}+ return token(INIT_LABEL);
^":" return token(INIT_REM);
{name}+ return token(INIT_COMMAND);
on return token(ECHO_ON);
off return token(ECHO_OFF);
"." return token(ECHO_DOT);
not return token(IF_NOT);
errorlevel return token(IF_ERRORLEVEL);
exist return token(IF_EXIST);
{delim}+ return token(SPACE);
"%"{name}+"%" return token(VARIABLE);
"%"{digit} return token(PARAMETER);
%%{name}+ return token(FOR_VARIABLE);
in return token(FOR_IN);
do return token(FOR_DO);
"("[^)]+")" return token(FOR_WORDLIST);
"\n" return token(EOL);
{delim}+ ;
{legal}+ return token(WORD);
{other} return token(OTHER);

%%

#ifdef __BORLANDC__
#pragma option -w
#pragma warn -use-
#pragma warn -ccc-
#endif

/**************************************************************************/
/* global variables */
/**************************************************************************/
int cmdtoken; /* first token in each batch line */
int errorcount=0; /* syntax error counter */
int errorlevelflag=0; /* control use of "set errorlevel=$status" */
int indentlevel=0; /* indent level of output */

/**************************************************************************/
/* support functions */
/**************************************************************************/
/* report any errors */
int reporterrors()
{
char s[7];

if (errorcount) {
itoa(errorcount, s, 10);
fputs("\n\nNUMBER OF ERRORS = ", stderr);
fputs(s, stderr);
fputs("\n\n", stderr);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

/* abnormal termination */
void terminate(void)
{
putln();
puts(" ### PREMATURE END-OF-FILE ###");
errorcount++;
exit(reporterrors());
}

/* wrapper for yylex */
int lex(void)
{
int result; /* return result */
static int count=0; /* count number of times yylex returns 0 */

result = yylex();
if (!result) {
if (count==1) {
terminate();
} else { /* handle possible premature eof */
count++;
result = EOL;
}
}
return result;
}

/* indent output based on global indentlevel */
void indent(void)
{
int i;

for (i=0; i }

/* put token back to input stream */
void putbacktoken(void)
{
yyless(0);
}

/* translate character in string s */
char *tr(char *s, int oldch, int newch)
{
char *sp = s;

do {
if (*sp == oldch) *sp = newch;
} while (*sp++);
return s;
}

/* convert replaceable parameter, e.g. %1 -> $1 */
char *cvt_parameter(char *s)
{
strcpy(textbuf, s);
*textbuf='$';
return textbuf;
}

/* convert variable, e.g. %PATH% -> ${path} */
char *cvt_variable(char *s)
{
char *sp;

strcpy(textbuf, "${");
sp = s;
sp++;
strncat(textbuf, sp, yyleng-2);
strcat(textbuf, "}");
return strlwr(textbuf);
}

/* convert variable used with 'for' keyword, e.g. %%F -> ${f} */
char *cvt_for_variable(char *s)
{
char *sp;

strcpy(textbuf, "${");
sp = s;
sp += 2;
strncat(textbuf, sp, yyleng-2);
strcat(textbuf, "}");
return strlwr(textbuf);
}

/* convert variable used with set keyword, e.g. ${f} -> f */
char *cvt_set_variable(int token)
{
int len;

switch(token) {
case VARIABLE:
case FOR_VARIABLE:
len = strlen(textbuf)-2;
memmove(textbuf, textbuf+2, len);
textbuf[len-1]='\0';
break;
default:
break;
}
return textbuf;
}

/* convert from batch format to csh format */
char *cvt_token(int token, char *s)
{
char *sp, *tp=textbuf;

switch(token) {
case PARAMETER:
if (s) cvt_parameter(s);
else cvt_parameter(yytext);
break;
case VARIABLE:
if (s) cvt_variable(s);
else cvt_variable(yytext);
break;
case FOR_VARIABLE:
if (s) cvt_for_variable(s);
else cvt_for_variable(yytext);
break;
case SPACE:
if (s) strcpy(textbuf, s);
else strcpy(textbuf, yytext);

/* translate delimiter if set or path */
if (cmdtoken==INIT_SET || cmdtoken==INIT_PATH) {
tr(textbuf, ';', ' ');
}
break;
default:
if (s) strcpy(textbuf, s);
else strcpy(textbuf, yytext);

tr(textbuf, '/', '-'); /* translate options specifier */
tr(textbuf, '\\', '/'); /* translate directory separator */

/* if path contains a drive specifier, remove it */
sp = strchr(textbuf, ':');
if (sp && sp != tp) {
if (isalpha(*(sp-1)) && *(sp+1) == '/') {
memmove(sp-1, sp+1, strlen(sp));
}
}

/* convert to lower case if not remark or echo, or contains path */
if (!(cmdtoken==INIT_REM || cmdtoken==INIT_ECHO) || strchr(tp, '/')) {
strlwr(tp);
}
break;
}
return tp;
}

/* print text associated with remaining tokens on line */
void puttokln(int token, char *start, char *end)
{
char *tp;

BEGIN(TEXT);
ckeol(token);
if (start) {
tp = cvt_token(token, start);
/* translate names of common commands */
if (!strcmp(tp, "attrib")) strcpy(tp, "chmod");
else if (!strcmp(tp, "chdir")) strcpy(tp, "cd");
else if (!strcmp(tp, "cls")) strcpy(tp, "clear");
else if (!strcmp(tp, "command")) strcpy(tp, "csh");
else if (!strcmp(tp, "copy")) strcpy(tp, "cp");
else if (!strcmp(tp, "del")) strcpy(tp, "rm");
else if (!strcmp(tp, "dir")) strcpy(tp, "ls");
else if (!strcmp(tp, "erase")) strcpy(tp, "rm");
else if (!strcmp(tp, "md")) strcpy(tp, "mkdir");
else if (!strcmp(tp, "move")) strcpy(tp, "mv");
else if (!strcmp(tp, "print")) strcpy(tp, "pr");
else if (!strcmp(tp, "rd")) strcpy(tp, "rmdir");
else if (!strcmp(tp, "ren")) strcpy(tp, "mv");
else if (!strcmp(tp, "rename")) strcpy(tp, "mv");
else if (!strcmp(tp, "time")) strcpy(tp, "date");
else if (!strcmp(tp, "type")) strcpy(tp, "cat");
else if (!strcmp(tp, "xcopy /s")) strcpy(tp, "cp -r");
else if (!strcmp(tp, "xcopy")) strcpy(tp, "cp");
putstr(tp);
}
while ((token=lex())!=EOL) {
putstr(cvt_token(token, NULL));
}
if (end) {
putstr(end);
}
putln();
}

/* eat remainder of line */
void eattokens(void)
{
BEGIN(TEXT);
while (lex()!=EOL) ;
}

/**************************************************************************/
/* batch keyword functions */
/**************************************************************************/
void kw_call(void)
{
errorlevelflag=0;
indent();
puttokln(INIT_CALL, "csh ", NULL);
}

void kw_command(void)
{
int token;

errorlevelflag=0;
putbacktoken();
BEGIN(TEXT);
token = lex();
indent();
puttokln(token, yytext, NULL);
}

void kw_echo(void)
{
int token;

BEGIN(ECHOS);
token = lex();
switch(token) {
case ECHO_ON:
eattokens();
break;
case ECHO_OFF:
eattokens();
break;
case ECHO_DOT:
indent();
puts("echo ''");
eattokens();
break;
case EOL:
break;
default:
indent();
putstr("echo ");
putbacktoken();
puttokln(INIT_ECHO, NULL, NULL);
break;
}
}

void kw_for(void)
{
int token;

BEGIN(FOR);
indent();
putstr("foreach ");

/* get variable */
token = lex();
ckeol(token);
cktok(token, FOR_VARIABLE);
if (yyleng>2) putstr(yytext+2);

/* check for "in" keyword */
token = lex();
ckeol(token);
cktok(token, FOR_IN);
putstr(" ");

/* get wordlist */
token = lex();
ckeol(token);
cktok(token, FOR_WORDLIST);
putstr(yytext);

/* check for "do" keyword */
token = lex();
ckeol(token);
cktok(token, FOR_DO);
putln();

/* process command */
indentlevel++;
if (dispatch()==EOF) terminate();
indentlevel--;

/* end foreach */
indent();
puts("end");
}

void kw_goto(void)
{
indent();
puttokln(INIT_GOTO, yytext, NULL);
}

void kw_if(void)
{
int token;
int not = 0;
char *sp, strbuf[STRBUFSIZE];

BEGIN(TEXT);
for (;;) {
while ((token=lex())==SPACE) ;
ckeol(token);
switch (token) {
case IF_NOT:
not = !not;
continue;
case IF_ERRORLEVEL:
if (errorlevelflag==0) {
errorlevelflag=1;
indent();
puts("set errorlevel=$status");
}
while ((token=lex())==SPACE) ;
ckeol(token);
indent();
if (not) {
putstr("if (${errorlevel} < ");
} else {
putstr("if (${errorlevel} >= ");
}
do {
putstr(cvt_token(token, NULL));
} while (!((token=lex())==SPACE||token==EOL));
break;
case IF_EXIST:
while ((token=lex())==SPACE) ;
indent();
if (not) {
putstr("if (! ");
} else {
putstr("if (");
}
ckeol(token);

/* get file or directory name */
strcpy(strbuf, "");
do {
strcat(strbuf, cvt_token(token, NULL));
} while (!((token=lex())==SPACE||token==EOL));
sp = strstr(strbuf, "/nul");
if (sp && sp==strbuf+strlen(strbuf)-4) { /* directory */
putstr("-d \"");
*sp = '\0';
} else { /* file */
putstr("-f \"");
}

/* print file or directory name */
putstr(strbuf);
putstr("\"");
break;
default: /* must be string comparison */
indent();
putstr("if (");
do {
putstr(cvt_token(token, NULL));
} while (!((token=lex())==SPACE||token==EOL));
if (not) {
putstr(" != ");
} else {
putstr(" == ");
}
ckeol(token);
while ((token=lex())==SPACE) ;
ckeol(token);
do {
putstr(cvt_token(token, NULL));
} while (!((token=lex())==SPACE||token==EOL));
break;
}
break;
}
putstr(")");
ckeol(token);
puts(" then");

/* process command */
indentlevel++;
if (dispatch()==EOF) terminate();
indentlevel--;

/* end if */
indent();
puts("endif");
}

void kw_label(void)
{
strcpy(textbuf, yytext+1);
strcat(textbuf, ":");
puts(strlwr(textbuf));
eattokens();
}

void kw_ln(void)
{
putln();
}

void kw_path(void)
{
int token;

BEGIN(TEXT);
while ((token=lex())==SPACE) ;
indent();
if (token==EOL) {
putstr("unset path");
putln();
} else {
putstr("set path=(");
puttokln(token, yytext, ")");
}
indent();
puts("rehash");
}

void kw_pause(void)
{
indent();
puts("echo -n 'Press the Enter key to continue...'");
indent();
puts("echo -n $?");
eattokens();
}

void kw_remark(void)
{
puttokln(INIT_REM, "#", NULL);
}

void kw_set(void)
{
int token;

BEGIN(TEXT);
while ((token=lex())==SPACE) ;
if (token==EOL) {
indent();
puts("set");
return;
}
cvt_token(token, NULL);
cvt_set_variable(token);
if (!stricmp(textbuf, "path")) {
kw_path();
return;
}

/* variable name in textbuf, variable contents in yytext */
while ((token=lex())==SPACE) ;
indent();
if (token==EOL) {
putstr("unset ");
putstr(textbuf);
putln();
} else {
putstr("set ");
putstr(textbuf);
putstr("=\"");
puttokln(token, yytext, "\"");
}
}

void kw_shift(void)
{
indent();
puttokln(INIT_SHIFT, "shift ", NULL);
}

/**************************************************************************/
/* keyword function table */
/**************************************************************************/
FNTBL fntbl[] =
{
{token(INIT_CALL), kw_call},
{token(INIT_COMMAND), kw_command},
{token(INIT_ECHO), kw_echo},
{token(INIT_FOR), kw_for},
{token(INIT_GOTO), kw_goto},
{token(INIT_IF), kw_if},
{token(INIT_LABEL), kw_label},
{token(EOL), kw_ln},
{token(INIT_PATH), kw_path},
{token(INIT_PAUSE), kw_pause},
{token(INIT_REM), kw_remark},
{token(INIT_SET), kw_set},
{token(INIT_SHIFT), kw_shift}
};

#define N_FNTBL sizeof(fntbl)/sizeof(fntbl[0])

/**************************************************************************/
/* function dispatcher */
/**************************************************************************/
int dispatch(void) /* returns 0=success; EOF=end of file */
{
int i, token;

BEGIN(INITIAL);
token = yylex();
if (token) {
for (i = 0; i < N_FNTBL; i++) {
if (token == fntbl[i].token) {
cmdtoken = token;
fntbl[i].fn();
return 0;
}
}

/* no match, call kw_command() */
cmdtoken = INIT_COMMAND;
kw_command();
return 0;
}
return EOF;
}

/**************************************************************************/
/* main function */
/**************************************************************************/
int main()
{
puts("#! /bin/csh");
while (dispatch()!=EOF) ;
return reporterrors();
}