System Software Lab Manual
System Software Lab Manual
ACCREDATED BY NBA
06CSL68
6TH SEMESTER
Part A
LEX AND YACC PROGRAMS:
PART B
UNIX PROGRAMMING:
1) a. Non-recursive shell script that accepts any number of arguments and prints them in
the Reverse order, ( For example, if the script is named rargs, then executing rargs
A B C should produce C B A on the standard output).
b. C program that creates a child process to read commands from the standard input and
execute them (a minimal implementation of a shell – like program). You can assume
that no arguments will be passed to the commands to be executed.
2) a. Shell script that accepts two file names as arguments, checks if the permissions for
these files are identical and if the permissions are identical, outputs the common
permissions, otherwise outputs each file name followed by its permissions.
b. C program to create a file with 16 bytes of arbitrary data from the beginning and
another 16 bytes of arbitrary data from an offset of 48. Display the file contents to
demonstrate how the hole in file is handled.
3) a. Shell function that takes a valid directory names as an argument and Recursively
descends all the subdirectories, finds the maximum length of any file in that hierarchy
and writes this maximum value to the standard output.
b. C program that accepts valid file names as command line arguments and for each of
the arguments, prints the type of the file (Regular file, Directory file, Character special
file, Block special file, Symbolic link etc.)
4) a. Shell script that accepts file names specified as arguments and creates a shell script
that contains this file as well as the code to recreate these files. Thus if the script
generated by your script is executed, it would recreate the original files(This is same as
the “bundle” script described by Brain W. Kernighan and Rob Pike in “ The Unix
Programming Environment”, Prentice – Hall India).
b. C program to do the following: Using fork( ) create a child process. The child process
prints its own process-id and id of its parent and then exits. The parent process waits for
its child to finish (by executing the wait( )) and prints its own process-id and the id of its
child process and then exits.
COMPILER DESIGN:
5) Write a C program to implement the syntax-directed definition of “if E then S1” and
“if E then S1 else S2”. (Refer Fig. 8.23 in the text book prescribed for 06CS62
Compiler Design, Alfred V Aho, Ravi Sethi, Jeffrey D Ullman: Compilers- Principles,
Techniques and Tools, Addison-Wesley, 2007.)
6) Write a yacc program that accepts a regular expression as input and produce its parse
tree as output.
Instructions:
In the examination, a combination of one LEX and one YACC problem has to be asked
from Part A for a total of 25 marks and one programming exercise from Part B has to be
asked for a total of 25 marks.
PART A
LEX :
1) a. Program to count the number of characters, words, spaces and lines in a given
input file.
%{
#include<stdio.h>
int cc=0,bc=0,wc=0,lc=0;
%}
%%
[^ \t\n]+ { wc++;
cc=cc+yyleng;
}
\n lc++;
" " bc++;
\t bc=bc+5;
%%
main(int argc,char *argv[])
{
if (argc!=2) {
printf("\nusage:./a.out filename\n");
return(0);
}
yyin=fopen(argv[1],"r");
yylex();
printf("\n no of lines are %d\n",lc);
printf("\n no of words are %d\n",wc);
printf("\n no of blanks are %d\n",bc);
printf("\n no of character are %d\n",cc);
}
Sample Input/Output:
$ lex prga1a.l
$ cc lex.yy.c
$ ./a.out ben10
no of lines are
no of words are
no of blanks are
no of character
$ cat ben10
Ben discovers a strange device, the Omnitrix, which locks itself on his wrist.
Each alien has its own set of special abilities that Ben can use, while at the same
time still maintaining his 10-year-old personality.
%{
#include<stdio.h>
int c=0;
%}
%%
("/*"[ a-zA-Z0-9\n\t]*"*/") c++;
("//"[\n]?[ a-zA-Z0-9]*) c++;
[a-zA-Z0-9(){}.\;#<>]* {fprintf(yyout,"%s",yytext);}
%%
Sample Input/Output :
$vi prga1b.l
$ lex prga1b.l
$ cc lex.yy.c -lfl
$ ./a.out test.c out.c
no of comment lines is 4
$ cat out.c
#include<stdio.h>
int main()
{
int a,b;
printf("this is test program ");
return 0;
}
$ cat test.c
%{
#include<stdio.h>
int nplus=0,nminus=0,nmul=0,id=0,ndiv=0,flag1=0,flag2=0;
%}
%%
[(] {flag1++;}
[)] {flag1--;}
[ a-zA-Z0-9]+ {flag2++;id++;}
[+] {flag2--;nplus++;}
[-] {flag2--;nminus++;}
[*] {flag2--;nmul++;}
[/] {flag2--;ndiv++;}
%%
main()
{
printf("\nenter a valid arithematic expression\n");
yylex();
if(flag1!=0||flag2!=1)
printf("invalid expression");
else {
printf("\nValid expression\n");
printf("addition(+)=%d\n",nplus);
printf("subtraction(-)=%d\n",nminus);
printf("multiplication(*)=%d\n",nmul);
printf("division(/)=%d\n",ndiv);
printf("\nid=%d",id);
}
Sample Input/Output :
$ lex prog2a.l
$ cc lex.yy.c -lfl
$ ./a.out
Sample Input/Output :
Run 1:
$ lex prog2b.l
$ cc lex.yy.c -lfl
$ ./a.out
Noddy and his friends have been exploring the magical world.
sentence is compound
Run 2:
$ ./a.out
enter the sentence
Sentence is simple
3) Program to recognize and count the number of identifiers in a given input file.
%{
#include<stdio.h>
int count=0;
%}
%%
"int" |
"float" |
"double" |
"char" { char ch;
ch=input();
while(1) {
if(ch==',') count++;
if(ch==';') {
count++;
break;
}
if(ch=='\n') break;
ch=input();
}
}
. | '\n' ;
%%
int main(int argc,char *argv[])
{
if(argc!=2)
printf("\n\nINVALID INPUT\n\n");
else {
yyin=fopen(argv[1],"r");
if(yyin) {
yylex();
printf("\nNo of identifiers = %d\n",count);
} else
printf("\nError in opening the file\n");
}
printf("\n");
}
Sample Input/Output :
$ lex prg3.l
$ cc lex.yy.c -lfl
$ ./a.out out.c
No of identifiers = 1
$ cat out.c
//to print a message
// hello*/
#include<stdio.h>
main()
{
int var=0; //dummy variablr
writef("hello");//aprint the message
getch();
}
PART A
YACC :
Lex part :
%{
#include "y.tab.h"
%}
%%
[a-zA-Z] {return ALPHA;}
[0-9]+ {return NUMBER;}
[\t\n]+ ;
. {return yytext[0];}
%%
Yacc part :
%{
#include<stdio.h>
%}
%token NUMBER ALPHA
%left '+''-'
%left '*''/'
%left '('')'
%%
expr:'+'expr
|'-'expr
|expr'+'expr
|expr'-'expr
|expr'*'expr
|expr'/'expr
|'('expr')'
|NUMBER
|ALPHA
;
%%
int main()
{
printf("enter an arithematic expression\n");
yyparse();
printf("arithematic expression is valid\n");
return 0;
}
int yyerror(char *msg)
{
printf("\n%s",msg);
printf("\narithematic expression is invalid");
exit(0);
}
Sample Input/Output :
$ lex prog1.l
$ yacc -d prog1.y
$ cc -c lex.yy.c y.tab.c
$ cc -o a.out lex.yy.o y.tab.o -lfl
$ ./a.out
enter an arithmetic expression
(a+d)*(c-e)
Arithmetic expression is valid
Lex Part :
%{
#include "y.tab.h"
%}
%%
[a-zA-Z] return L;
[a-zA-Z0-9] return D;
. return P;
%%
Yacc Part :
%{#include<stdio.h>
%}
%token L D P
%%
var:L X
X:X D
| {printf("\nvalid variable"); return 0;}
P {;}
%%
main()
{
printf("\nEnter variable");
yyparse();
}
yyerror()
{
printf("\nInvalid variable");
}
Alternate Program
%{
#include<stdio.h>
#include<ctype.h>
%}
%token LETTER DIGIT
%%
var : LETTER st '\n' {printf("\nValid variable\n");return 0;}
;
st : LETTER
| DIGIT
| DIGIT st
| LETTER st
;
%%
int yylex()
{
char c;
while((c=getchar())==' '||c=='\t');
if(isalpha(c)) return LETTER;
if(isdigit(c)) return DIGIT;
return c;
}
int main()
{
printf("\nEnter the variable : ");
yyparse();
return 0;
}
int yyerror()
{
printf("\nInvalid variable\n");
return 0;
}
Sample Input/Output :
1 run :
$ lex prog4b.l
$ yacc -d prog4b.y
$ cc -c lex.yy.c y.tab.c
$ cc -o a.out lex.yy.o y.tab.o -lfl
$ ./a.out
Enter variable:
#71
Invalid variable
2 run :
Enter variable:
number71
valid variable
3 run :
Enter variable:
7edf
Invalid variable
Lex part :
%{
#include<stdio.h>
#include"y.tab.h"
extern int yylval;
%}
%%
[0-9]+ { yylval=atoi(yytext);
return NUM;
}
[\t] ;
\n return 0;
. return yytext[0];
%%
Yacc Part
%{
#include<stdio.h>
%}
%token NUM
%left '+' '-'
%left '*' '/'
%left '(' ')'
%%
expr: e
{ printf("result:%d\n",$$);
return 0;
}
e:e'+'e {$$=$1+$3;}
|e'-'e {$$=$1-$3;}
|e'*'e {$$=$1*$3;}
|e'/'e {$$=$1/$3;}
|'('e')' {$$=$2;}
| NUM {$$=$1;}
;
%%
main()
{
printf("\n enter the arithmetic expression:\n");
yyparse();
printf("\n valid expression\n");
}
yyerror()
{
printf("\n invalid expression\n");
exit(0);
}
Sample Input/Output :
$ lex prog5.l
$ yacc -d prog5.y
$ cc -c lex.yy.c y.tab.c
$ cc -o a.out lex.yy.o y.tab.o -lfl
$ ./a.out
valid expression
5 b) Program to recognize strings 'aaab', 'abbb', 'ab', 'a' using the grammer.
(an bn ,n>=0)
Lex part :
%{
#include "y.tab.h"
%}
%%
a return A;
b return B;
.|\n return yytext[0];
%%
Yacc Part :
%{
#include<stdio.h>
int valid=1;
%}
%token A B
%%
str:S'\n' {return 0;}
S:A S B
|
;
%%
main()
{
printf("Enter the string:\n");
yyparse();
if(valid==1)
printf("\nvalid string");
}
yyerror()
{
valid=0;
printf("\ninvalid string");
return 1;
}
Sample Input/Output :
$ lex prog5b.l
$ yacc -d prog5b.y
$ cc -c lex.yy.c y.tab.c
$ cc -o a.out lex.yy.o y.tab.o -lfl
$ ./a.out
Enter the string:
aaaabb
Invalid string
Lex Part :
%{
#include "y.tab.h"
%}
%%
a return A;
b return B;
.|\n return yytext[0];
%%
Yacc Part :
%{
#include<stdio.h>
int valid=1;
%}
%token A B
%%
str:S'\n' {return 0;}
S:A S B
|
;
%%
main()
{
printf("Enter the string:\n");
yyparse();
if(valid==1)
printf("\nValid string");
yyerror()
{
valid=0;
printf("\nInvalid string");
return 1;
}
Sample Input/Output :
$ lex prog6.l
$ yacc -d prog6.y
$ cc -c lex.yy.c y.tab.c
$ cc -o a.out lex.yy.o y.tab.o -lfl
$ ./a.out
Enter the string:
aaaabb
Invalid string
Enter the string:
aaaaaaaaaab
valid string
PART B
Unix Programming:
Shell Programming :
The Shell is one of the major components of the Unix system. As a command
interpreter, it provides an interface between the user and the operating system.
The shell is also a programming language that executes shell scripts in the
interpretive mode – one line at a time.
The Shell programs or shell scripts are executable text files that contain UNIX
commands.
The Unix Systems offers a variety of shells like Bourne shell , C shell, Korn
shell and bash(born again shell) shell for you to choose.
Shell script (named first) that displays the current date, the users on the system
and a welcome message for the user logged in.
date
who
echo “Welcome $LOGNAME”
$ sh first.sh
Sat Sep 30 14:42:39 PDT 2007
root tty01 Sep 30 13:32
welcome root
1) a. Non-recursive shell script that accepts any number of arguments and prints
them in the Reverse order, (For example, if the script is named ranges, then
executing ranges A B C should produce C B A on the standard output).
Sample input/output:
$ sh 1a.sh a b c d
Input string is: a b c d
Reversed string is: d c b a
1) b. C program that creates a child process to read commands from the standard
input and execute them (a minimal implementation of a shell – like program). You
can assume that no arguments will be passed to the commands to be executed.
#include<stdio.h>
int main()
{
char str[10];
int pid;
pid=fork();
if(!pid)
{
printf("Child process...");
printf("\nEnter a command:");
scanf("%s",str);
system(str);
printf("Finished with child");
}
else
{
wait();
printf("\nParent Process");
}
return 0; }
Sample input/output :
$ ./a.out
Child process...
Enter a command:date
Wed Feb 7 21:52:00 IST 2007
Finished with child
Parent Process
2) a. Write a shell script that accepts two filenames as arguments, checks if the
permissions for these files are identical & if the permissions are identical, outputs
the common permissions, otherwise outputs each file names followed by its
permissions
fi
Sample input/output :
Run 1:
$ sh 2a.sh 4a.l 4a.sh
file 4a.l has file permissions : rw-r--r--
file 4a.sh has file permissions : rwxr-xr-x
Run 2:
2) b. Write a C program to create a file with 16 bytes of arbitrary data fro the
beginning and another 16 bytes of arbitrary data from an offset of 48.Display the
file contents to demonstrate how the hole in file is handled.
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
int main()
{
char buf1[]="123456789ABCDEFG";
char buf2[]="HIJKLMNOPQRSTUVW";
int fd;
fd=creat("t.txt",O_WRONLY|777);
write(fd,buf1,16);
lseek(fd,48,SEEK_SET);
write(fd,buf2,16);
return 0;
}
Sample input/output :
$ ./a.out
$ vi t.txt
3) a. Shell script that takes a valid directory names as an argument and recursively
descents all the subdirectories, finds the maximum length of any file in that
hierarchy and writes this maximum value to the standard output.
if [ $# -ne 1 ]
then
echo "Usage : $0 directory"
exit 1
fi
ls -Rl $1 | grep "^-" | sort -n -k 5,9 | tee f1
echo "Maximum length of file is "
tail -1 f1 | cut –d “ ” –f 5,8
Sample input/output :
$ sh 3a.sh .
-rw-r--r-- 1 root root 76 Feb 7 21:43 y.tab.h
-rw-r--r-- 1 root root 90 Feb 7 20:37 cprog.c
-rw-r--r-- 1 root root 120 Feb 6 22:59 6.l
-rw-r--r-- 1 root root 130 Feb 6 22:33 5b.l
-rw-r--r-- 1 root root 152 Feb 6 23:15 4b.l
-rw-r--r-- 1 root root 176 Feb 6 22:18 5a.l
Maximum length of file is
176 7 22:10 5a.l
3) b. Write a C Program that accepts valid file names as command line Arguments
& for each of the arguments, prints the type of the file. (Regular file, Directory file,
Character special file, Block special file, Symbolic link etc.)
#include <sys/stat.h>
#include<stdio.h>
int main(int argc,char* argv[])
{
int i;
struct stat file;
for(i=1;i<argc;i++)
{
if(lstat(argv[i],&file)!=0) {
printf("File %s does not exits",argv[i]);
continue;
}
printf("\nFile %s is a ",argv[i]);
if(S_ISREG(file.st_mode)) printf("Regular File");
else if(S_ISDIR(file.st_mode)) printf("Directory File");
else if(S_ISCHR(file.st_mode)) printf("Character Device File");
else if(S_ISBLK(file.st_mode)) printf("Block Device File");
Sample input/output :
Run 1:
$ ./a.out 3a.sh
File 3a.sh is a Regular File
Run 2:
4) a. Shell script that accepts file names specified as arguments and creates a shell
script that contains this file as well as the code to recreate these files. Thus if the
script generated by your script is executed, it would recreate the original files (This
is same as the “bundle” script described by Brain W. Kernighan and Rob Pike in
“The Unix Programming Environment”, Prentice – Hall India).
for x in $*
do
echo "cat > $x << here
abc
def
ghi
here"
done > recreate
Sample input/output :
here
$ sh recreate
$ ls
file1 file2 recreate
$ cat file1
abc
def
ghi
$ cat file2
abc
def
ghi
4) b. Write a C program to create child process. The child process prints its own
process-id and id of its parent and then exits. The parent process waits for its child
to finish & prints its own process id & the id of its child process and then exits.
int main()
{
char str[10];
int pid;
pid=fork();
if(!pid)
{
printf("Child process...");
printf("\n\nChild PID : %d",getpid());
printf("\nParent PID : %d",getppid());
printf("\n\nFinished with child\n");
}
else
{
wait();
printf("\nParent process");
printf("\nPARENT PID : %d",getpid());
printf("\nChild PID : %d",pid);
}
return 0;
}
Sample input/output :
$ ./a.out
Child process...
Child PID : 4145 Parent process
Parent PID : 4144 PARENT PID : 4144
Finished with child Child PID : 4145
COMPILER DESIGN:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int parsecondition(char[],int,char*,int);
void gen(char[],char[],char[],int);
int main()
{
int counter=0,stlen=0,elseflag=0;
char stmt[60];
char strB[54];
char strs1[50];
char strs2[45];
printf("\nFormat of 'if' statement \nExample : \n");
printf(" if( a < b ) then ( s = a );\n");
elseflag=1;
printf("\nParsing the input statement..");
gen(strB,strs1,strs2,elseflag);
return 0;
}
return 0;
}
int parsecondition(char input[],int cntr,char *dest,int totallen)
{
int index=0,pos=0;
while(input[cntr]!='(' && cntr<=totallen)
cntr++;
if(cntr>=totallen)
return 0;
index=cntr;
while(input[cntr]!=')') cntr++;
if(cntr>=totallen)
return 0;
while(index<=cntr)
dest[pos++]=input[index++];
dest[pos]='\0';
return cntr;
}
void gen(char B[],char s1[],char s2[],int elsepart)
{
int Bt=101,Bf=102,Sn=103;
printf("\n\t if %s goto %d ",B,Bt);
printf("\n\t goto %d ",Bf);
printf("\n\t %d : ",Bt);
printf("%s",s1);
if(!elsepart)
printf("\n\t%d : Exit\n",Bf);
else
{
printf("\n\tgoto %d",Sn);
printf("\n\t%d : %s",Bf,s2);
printf("\n\t%d :Exit\n ",Sn);
}
6. Write a yacc program that accepts a regular expression as input and produce its
parse tree as output.
%{
#include<ctype.h>
char str[20];
int i=0;
%}
%token id
%left '+''/''*''-'
%%
E:S {infix_postfix(str);}
S : S '+' T
| S '-' T
|T
T : T '*' F
| T '/' F
|F
F : id
| '(' S ')'
;
%%
#include<stdio.h>
main()
{
printf("\nEnter an expression : ");
yyparse();
}
yyerror()
{
printf("invalid");
}
yylex(){
char ch=' ';
while(ch!='\n'){
ch=getchar();
str[i++]=ch;
if(isalpha(ch)) return id;
if(ch=='+'||ch=='*'|| ch=='-'||ch=='/') return ch;}
str[--i]='\0';
return(0);
exit(0);
}
void push(char stack[],int *top,char ch)
{
stack[++(*top)]=ch;
}