L. D. College of Engineering Lab Manual: System Software (3160715)
L. D. College of Engineering Lab Manual: System Software (3160715)
College of Engineering
Opp Gujarat University, Navrangpura, Ahmedabad - 380015
LAB MANUAL
Branch: Computer Engineering
Faculty Details:
1) Prof. Reshma Dayma
System Software (3160715)
Certificate
Term: 2021-22
SIGN OF FACULTY
Term: 2021-22
Class:A
1
CO1
2
CO2
3
CO3
4
CO4
5
CO4
6
CO4
7
CO4
8
CO4
9
CO4
10
CO5
11
CO1
COURSE CURRICULUM
COURSE TITLE: System Software
(Code: 3160715)
Degree Programmes in which this course is Semester in which offered
offered
1. RATIONALE
2. COMPETENCY
The course content should be taught to impart knowledge about System Software which is most
important component of any computer system. The aim of the course is to enable students to
understand fundamentals of System Software, different types of language process, how they
perform the task, data structure required for that, different approaches to perform the task.
3. COURSE OUTCOMES
Computer Engineering Department, L. D. College of Engineering, Ahmedabad-15 5
System Software (3160715)
1. C compiler
2. Linux / Unix
3. Lex tool
4. YACC tool
Practical – 1
#include<stdio.h>
#include<ctype.h>
#include<string.h>
int i=0,id=0,kw=0,num=0,op=0;
char keys[32][10]={"auto","break","case","char","const","continue","default",
"do","double","else","enum","extern","float","for","goto",
"if","int","long","register","return","short","signed",
"sizeof","static","struct","switch","typedef","union",
"unsigned","void","volatile","while"};
main()
int j;
char fname[50];
FILE *f1;
//clrscr();
scanf("%s",fname);
f1 = fopen(fname,"r");
//f1 = fopen("Input","r");
if(f1==NULL)
exit(0);
while((ch=fgetc(f1))!=EOF)
for(j=0;j<=14;j++)
if(ch==oper[j])
printf("%c is an operator\n",ch);
op++;
str[i]='\0';
keyw(str);
for(j=0;j<=14;j++)
if(i==-1)
break;
if(ch==seps[j])
if(ch=='#')
while(ch!='>')
printf("%c",ch);
ch=fgetc(f1);
i=-1;
break;
if(ch=='"')
do
ch=fgetc(f1);
printf("%c",ch);
}while(ch!='"');
printf("\b is an argument\n");
i=-1;
break;
str[i]='\0';
keyw(str);
if(i!=-1)
str[i]=ch;
i++;
else
i=0;
//getch();
int k,flag=0;
for(k=0;k<=31;k++)
if(strcmp(keys[k],p)==0)
printf("%s is a keyword\n",p);
kw++;
flag=1;
break;
if(flag==0)
if(isdigit(p[0]))
printf("%s is a number\n",p);
num++;
else
//if(p[0]!=13&&p[0]!=10)
if(p[0]!='\0')
printf("%s is an identifier\n",p);
id++;
i=-1;
OUTPUT:
Practical – 2
AIM: Write a program in text file and generate SYMTAB and LITTAB.
Computer Engineering Department, L. D. College of Engineering, Ahmedabad-15 14
System Software (3160715)
#include<stdio.h>
#include<stdlib.h>
struct sys{
char n[20];
int ad;
};
int main()
char ch[50],c;
int adr=0,f=0,fl=0,sp=0,lp=0;
FILE *fr1;
fr1=fopen("inter.txt","r");
if(fr1== NULL){
printf("Failed to open\n");
printf("The ap is \n");
while((c=fgetc(fr1))!=EOF)
printf("%c",c);
FILE *fr;
fr=fopen("inter.txt","r");
c=fgetc(fr);
while((c)!=EOF)
if(c=='\t'&&f==0)
f =1;
else if(c!='\t'&&f==0&&fl==0)
int j=0;
while(c!='\t'&&(c)!=EOF){
stb[sp].n[j++]=c;
c=fgetc(fr);
stb[sp].n[j]='\0';
stb[sp++].ad=adr;
fl=1;
else if(c=='=')
int j=0;
while(c!='\n'&&(c)!=EOF){
lt[lp].n[j++]=c;
c=fgetc(fr);
lt[lp].n[j-1]='\0';
lt[lp++].ad=adr;
f=1;
else if(c=='\n')
{ adr++; f=0;fl=0; }
c=fgetc(fr);
printf("\n");
fclose(fr);
int i;
for(i=0;i<sp;i++)
printf("%s %d\n",stb[i].n,stb[i].ad);
printf("\nlt table\n");
for(i=0;i<lp;i++)
printf("%s %d\n",lt[i].n,lt[i].ad);
return 0;
OUTPUT:
Practical – 3
AIM: Demonstrate the Use macro features of C language.
Program
#include <stdio.h>
#define PI 3.1415
int main()
scanf("%f", &radius);
area = PI*radius*radius;
printf("Area=%.2f",area);
return 0;
#include<stdio.h>
void main()
int A = 8, B= 6, C = 4;
Output
Practical – 4
AIM: Write a Lexical Analyzer (using Lex utility for UNIX).
Program
%{
int no_of_lines = 0;
int no_of_chars = 0;
%}
taking input***/
%%
\n ++no_of_lines;
. ++no_of_chars;
end return 0;
%%
int yywrap(){}
yylex();
no_of_lines, no_of_chars );
return 0;
Output
Practical – 5
AIM: Demonstrate the use of YACC with example program.
Program
Yex file
%{
/* Definition section */
#include<stdio.h>
int flag=0;
%}
%token NUMBER
/* Rule Section */
%%
ArithmeticExpression: E{
printf("\nResult=%d\n", $$);
return 0;
};
E:E'+'E {$$=$1+$3;}
|E'-'E {$$=$1-$3;}
|E'*'E {$$=$1*$3;}
|E'/'E {$$=$1/$3;}
|E'%'E {$$=$1%$3;}
|'('E')' {$$=$2;}
| NUMBER {$$=$1;}
%%
//driver code
void main()
yyparse();
if(flag==0)
void yyerror()
flag=1;
Lex file
%{
/* Definition section */
#include<stdio.h>
#include "y.tab.h"
%}
/* Rule Section */
%%
[0-9]+ {
yylval=atoi(yytext);
return NUMBER;
[\t] ;
[\n] return 0;
. return yytext[0];
%%
int yywrap()
return 1;
Output
Practical – 6
AIM: Write a C program to left factor the given grammar.
Program
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
char ch,st[10][10],st1[10];
int i=0,j=0,w=0,p=0,k=0,l=0,z=0;
ch=getchar();
while(ch!='\n')
{ while(ch!='|')
st1[k++]=ch;
ch=getchar();
++w;
strcpy(st[w],st1);
for(i=k;i<10;i++)
st[w][i]='\0';
k=0;
ch=getchar();
printf("\n");
for(i=1;i<=w;i++)
printf("%s\n",st[i]);
for(i=1;i<w;i++)
{ for(j=0;j<10;j++)
if(st[i][j]==st[i+1][j])
st[0][j]=st[i][j];
else
break;
for(i=1;i<=w;i++)
{ for(j=0;j<10;j++)
if(st[0][j]==st[i][j])
st[0][j]=st[i][j];
else
for(l=j;l<10;l++)
{ st[0][j]='\0'; }
break;
z=strlen(st[0]); p=z;
st[0][z]='A';
st[0][++z]='*';
++z;
for(i=z;i<10;i++)
st[0][i]='\0';
for(i=1;i<=w;i++)
{ for(j=p;j<10;j++)
if(st[i][p]=='\0')
printf("E"); break;
if(st[i][j]=='\0')
break;
printf("%c",st[i][j]);
if(i!=w)
printf(" | ");
printf("\n\n");
Output
Practical – 7
AIM: Write a C program to remove the Left Recursion from a given grammar.
Program
#include<stdio.h>
#include<string.h>
#define SIZE 10
int main () {
char non_terminal;
char beta,alpha;
int num;
char production[10][SIZE];
int index=3; /* starting of the string following "->" */
printf("Enter Number of Production : ");
scanf("%d",&num);
printf("Enter the grammar as E->E-A :\n");
for(int i=0;i<num;i++){
scanf("%s",production[i]);
}
for(int i=0;i<num;i++){
printf("\nGRAMMAR : : : %s",production[i]);
non_terminal=production[i][0];
if(non_terminal==production[i][index]) {
alpha=production[i][index+1];
printf(" is left recursive.\n");
while(production[i][index]!=0 && production[i][index]!='|')
index++;
if(production[i][index]!=0) {
beta=production[i][index+1];
printf("Grammar without left recursion:\n");
printf("%c->%c%c\'",non_terminal,beta,non_terminal);
printf("\n%c\'->%c%c\'|E\n",non_terminal,alpha,non_terminal);
}
else
printf(" can't be reduced\n");
}
else
printf(" is not left recursive.\n");
index=3;
}
}
Output
Computer Engineering Department, L. D. College of Engineering, Ahmedabad-15 35
System Software (3160715)
Practical – 8
AIM: Write C program to Implement Recursive Descendent Parsing for the given Grammar.
E -> T + E / T
T -> F * T / F
F -> ( E ) / i
Program
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void match(char t);
void T();
void TS();
void F();
void ES();
void E();
char l;
void main()
{ printf("Enter string \n");
l=getchar();
printf("\n\n Production symbol\n"); printf("\tE\t%c\n",l);
E();
if(l=='$')
printf("\nsuccess\n");
else
printf("\nerror\n");
}
void match(char t)
{
if(t==l) l=getchar();
else printf("\nerror\n");
}
void E()
{ printf("\tT\t%c\n",l); T();
printf("\tES\t%c\n",l); ES();
}
void ES()
{ if(l=='+')
{
Computer Engineering Department, L. D. College of Engineering, Ahmedabad-15 37
System Software (3160715)
Output
Practical – 9
AIM: Implement Predictive Parser for the arithmetic expression grammar using YACC and Lex.
Program
%{
#include <stdio.h>
#include <string.h>
%}
%%
"(" {
top++;
stack[top] = '(';
"{" {
top++;
stack[top] = '{';
"[" {
top++;
stack[top] = '[';
")" {
if (stack[top] != '(') {
valid = 0;
valid=0;
else{
top--;
operands_count=1;
operators_count=0;
"}" {
if (stack[top] != '{') {
valid = 0;
valid=0;
else{
top--;
operands_count=1;
operators_count=0;
"]" {
if (stack[top] != '[') {
valid = 0;
valid=0;
else{
top--;
operands_count=1;
operators_count=0;
"+"|"-"|"*"|"/" {
operators_count++;
strcpy(operators[l], yytext);
l++;
[0-9]+|[a-zA-Z][a-zA-Z0-9_]* {
operands_count++;
strcpy(operands[j], yytext);
j++;
%%
int yywrap()
return 1;
int main()
int k;
yylex();
printf("\nValid Expression\n");
else
printf("\nInvalid Expression\n");
return 0;
Output
Practical – 10
AIM: Write a C program which generates Quadruple Table for the given postfix String.
Program
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void main()
gets(line);
for(i=0;i<20;i++) s[i]=0;
printf("op\ta1\ta2\tres\n");
for(i=2;line[i]!='\0';i++)
if(line[i]=='/' || line[i]=='*')
printf("\n");
if(s[i]==0)
if(s[i+1]==0)
printf(":=\t%c\t\t t%d\n",line[i+1],t);
s[i+1]=t++;
printf("%c\t",line[i]);
(s[i-1]==0)?printf("%c\t",line[i-1]):printf("t%d\t",s[i-1]);
printf("t%d \t t%d",s[i+1],t);
s[i-1]=s[i+1]=t++;
s[i]=1;
for(i=2;line[i]!='\0';i++)
if(line[i]=='+' || line[i]=='-')
printf("\n");
if(s[i]==0)
if(s[i+1]==0)
printf("%c\t",line[i]);
(s[i-1]==0)?printf("%c\t",line[i-1]):printf("t%d\t",s[i-1]);
printf("t%d \t t%d",s[i+1],t);
s[i-1]=s[i+1]=t++;
s[i]=1;
printf("\n:=\tt%d\t\t%c \n",t-1,line[0]);
Output
Practical – 11
ALGOL
First consider the data structures, which are very close to first generation structures. In
ALGOL 60 the block structure was introduced: the ability to create blocks of statements
for the scope of variables and the extent of influence of control statements. Along with
that, two different means of passing parameters to subprograms; call by value and call by
name. Structured control statements: if - then - else and the use of a general condition for
iteration control were also features, as was the concept of recursion: the ability of a
procedure to call itself.
One of the greatest impacts ALGOL 60 had was a result of its description as found in
Naur (1963). A major contribution of this report was the introduction of BNF notation for
defining the syntax of the language. Overall, ALGOL is considered to be perhaps the
most orthogonal programming language, meaning it has a relatively small number of
basic constructs and a set of rules for combining those constructs. Every construct has a
type associated with it and there are no restrictions on those types. In addition, most
constructs produce values. Several of ALGOL’s other characteristics are listed below:
Dynamic Arrays - one for which the subscript range is specified by variables so
that the size of the array is set at the time storage is allocated.
Reserved Words - the symbols used for keywords are not allowed to be used as
identifiers by the programmer.
User defined data types - allow the user to design data abstractions that fit
particular problems very closely.
ALGOL was used mostly by research computer scientists in the United States and in
Europe. Its use in commercial applications was hindered by the absence of standard
input/output facilities in its description and the lack of interest in the language by large
computer vendors. ALGOL 60 did however become the standard for the publication of
algorithms and had a profound effect on future language development.
C Language
It requires specific interactions, usually with very specific and sometimes rigid formats.
And because of the presence of several non-trivial structures and architectures as well as
non-traditional execution models, the need to build specific performance characteristics is
crucially important for the programmer.
Although several languages are being used for systems programming, C is the still the
ideal choice, due to its flexibility, efficiency, performance, and closeness to the hardware.
Let’s look at some other reasons why C continues to be the preferred systems
programming language:
Easy to code: One of the biggest reasons why C works so well for systems programming
is because it is easy to code. C’s direct 1-1 interaction with machine code means there are
no complicated built-in data structures like trees or tables. Since the programmer can see
any code and know exactly what it does in the hardware, the entire backend is
implemented by the programmer – unlike in other languages where the backend
implementation is not necessarily known to the programmer.
Low-level language: Another reason for using C for systems programming is its
proximity to the operating system. Since most C implementations compile directly to
machine code, the programmer has full power over what happens at the machine level.
There is no need for an interpreter or compiler. This feature makes C an efficient
language for systems programming because low-level resources, such as memory, can be
accessed effortlessly.
Explicit memory management: Another strong reason why C is so popular for systems
programming is the flexibility it offers for memory management. Unlike other
programming languages where a garbage collector takes care of memory allocation, C
allows programmers to do low-level memory handling themselves, giving them total
control over where, when, and how memory is allocated. Programmers can scale down a
program and run with a small amount of memory. This is extremely beneficial in today’s
digital age, where mobile devices demand that programmers keep memory requirement to
a minimum.
Flexible structure: Systems programming is never easy, especially while dealing with
large chunks of code. However, C’s flexible structure allows programmers to break down
the program into multiple blocks of code or functions for execution. So, it is easy to
understand and allows free movement of data across the different functions. Programmers
can manually copy data to different areas, move bits around, and process data in small
amounts. Although this is a tedious process, it is a lot more efficient – both in the usage
of RAM and in processing time, which is essential in systems programming.
doesn’t require an operating system. Those that do can be implemented minimally by the
programmer.
Compatibility: C is extremely compatible. Most languages that exist today already have
what it takes to interact and communicate with C. This means programmers can develop
a library in C using standard calling conventions, and have the confidence that every
other language can link to it, in a seamless manner. Any software developed using C#,
Java, Perl, Python, or PHP can all link with C libraries without much trouble.
RUST
Sponsored by Mozilla and developed actively over the past decade by a large and diverse
community of contributors, Rust supports many common low-level programming idioms
and APIs derived from modern C++. However, unlike C++, Rust enforces the safe usage
of these APIs with a strong static type system.
In particular, like Java, Rust protects programmers from memory safety violations (for
example, "use-after-free" bugs). But Rust goes further by defending programmers against
other, more insidious anomalies that no other mainstream language can prevent. For
example, consider data races: unsynchronized accesses to shared memory (at least one of
which is a write). Even though data races effectively constitute undefined (or weakly
defined) behavior for concurrent code, most "safe" languages (such as Java and Go)
permit them, and they are a reliable source of concurrency bugs.35 In contrast, Rust's
type system rules out data races at compile time.
Rust has been steadily gaining in popularity, to the point that it is now being used
internally by many major industrial software vendors (such as Dropbox, Facebook,
Amazon, and Cloudflare) and has topped Stack Overflow's list of "most loved"
programming languages for the past five years. Microsoft's Security Response Center
Team recently announced that it is actively exploring an investment in the use of Rust at
Microsoft to stem the tide of security vulnerabilities in system software.8
The design of Rust draws deeply from the wellspring of academic research on safe
systems programming. In particular, the most distinctive feature of Rust's design—in
relation to other mainstream languages—is its adoption of an ownership type system.
Ownership type systems help the programmer enforce safe patterns of lower-level
programming by placing restrictions on which aliases (references) to an object may be
used to mutate it at any given point in the program's execution.
However, Rust goes beyond the ownership type systems of prior work in at least two
novel and exciting ways:
Rust employs the mechanisms of borrowing and lifetimes, which make it much easier to
express common C++-style idioms and ensure they are used safely.
Rust also provides a rich set of APIs—for example, for concurrency abstractions,
efficient data structures, and memory management—which fundamentally extend the
power of the language by supporting more flexible combinations of aliasing and mutation
than Rust's core type system allows. Correspondingly, these APIs cannot be implemented
within the safe fragment of Rust: rather, they internally make use of potentially unsafe C-
style features of the language, but in a safely encapsulated way that is claimed not to
disturb Rust's language-level safety guarantees.
These aspects of Rust's design are not only essential to its success—they also pose
fundamental research questions about its semantics and safety guarantees that the
programming languages community is just beginning to explore.