0% found this document useful (0 votes)
50 views17 pages

New 5403

The document provides explanations of 10 important system software components: device driver, operating system, server, utility software, windowing system, application programs, root-user processes, assembler, compiler, interpreter, editor, loader, linker, and debugger. It also discusses the importance of information and communication technology (ICT) in daily life, including uses in education, e-commerce, banking, agriculture, medicine, and more. ICT has brought a revolution to everyday activities and improved quality of life.

Uploaded by

subhanak022
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
50 views17 pages

New 5403

The document provides explanations of 10 important system software components: device driver, operating system, server, utility software, windowing system, application programs, root-user processes, assembler, compiler, interpreter, editor, loader, linker, and debugger. It also discusses the importance of information and communication technology (ICT) in daily life, including uses in education, e-commerce, banking, agriculture, medicine, and more. ICT has brought a revolution to everyday activities and improved quality of life.

Uploaded by

subhanak022
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

Q.1 (a) List the software components of a computer. Explain at least ten of them in detail.

(b) Write down the importance of ICT in daily life use.

ANS:

System software components are defined as the software system designed to operate the computer’s
hardware; it provides a platform to run the application software and the basic functions for computer
usage. It protects the application programmer from the complexity and specific details of a particular
computer being used, especially the memory and the hardware features. The component of the software is
a self-contained system with one or more inputs and outputs channels; it has nothing to do with the input
and does not serve anything without the output.

System software components


Let us discuss System Software Components.

Device Driver
This system program controls the number of devices attached o the computer; it acts as a translator
between the user’s and the hardware device’s applications. A device driver tells the operating system how
the device will work on certain commands the user generates. With the device’s help, driver computer
hardware can interact with high-level system programs. For example, Wi-Fi driver, Bluetooth driver, etc.
Operating System
The operating system is the system which is the main part of the computer system, which manages the
hardware of the computer consisting of programs and data. The operating system has provided the
services so that we can execute the application software. The system program that makes it possible for
people to interact with computers is known as the operating system. It helps other programs to run and
control them.

Examples of computer operating systems are Linux, Microsoft Windows, OS X, and UNIX.

Server
It is a program; it works like a socket listener in a computer operating system. A server is a series of
computers connected to other computers. Private and public users in a network access the internet, and the
server provides that essential service.

Utility Software
It is used to manage hardware and application software and also performs small tasks. For example,
system utilities and virus scanners, etc.

Windowing System
This graphical user interface component supports the window manager’s implementation, provides
pointing devices like keyboards and mice, and supports graphics hardware.

Application programs
This is the top software layer; using it, we can perform tasks such as writing using a word processor
spreadsheets for accounting; it has two supporting layers: a device driver and an operating system.

Root-user processes
These are programs that users with root authority can run. Through all processes, root authority is given
to the administrator.

Assembler
An assembler, generally used in an assembly language program, is a program that converts the assembly
language into machine code. The compiler operates on basic commands and code, converting them into
binary code.

Compiler
The compiler converts the high-level programming language into the machine language. For example, in
C or C++ language, we should implement a particular source code in user-understandable format printf,
scanf, cout, such type of statements will generate in the user language. Hence, the compiler converts the
source code into the machine language format; machine language code means a target code, so we use a
compiler for conversion purposes.

Interpreter
The interpreter is also used to convert the source code into the target code, but the interpreter checks one
instruction at a time, which means it checks line-by-line code; it checks the first line, then converts it into
the target code, again checks the other programming line, and then convert into the target code.
Editor
The editor is the system program used to edit the text in the file. For example, we are all familiar with the
Microsoft Word processor, an editor whose main tasks are editing, traversing, viewing, and displaying the
text. Editor means editing the particular text or file per the user’s requirement. In addition, it links extra
files and extra library files. The type of editors is Line Editor, Screen Editor, Word Processor, and
Structure Editor.

Loader
The loader loads the complete program into the memory. When we save a particular program at that time,
the program will be stored in the secondary memory. Still, when we compile and execute a specific
program, the program will be executed into the primary memory. Hence, the loader converts the
program’s secondary memory to primary memory. It loads a particular program into the secondary to
primary memory.

Linker
This program links the user’s program to another program or library. It connects two or more modules
into the memory and prepares for execution. It integrates the necessary functions required by the program.
Some programming files use import functions in different libraries; for example, if we want to use the
square-root function in our code, we must import ‘math. We include the ‘H’ library in our programming,
and the linker generates the concept of linking these libraries with our programming file.

Debugger
A debugger is a computer program that finds errors, also called bugs, in source code. It provides the
facility to halt at any point and check the changes made in the program.

Macro
A macro processor can replace this group of instructions when called. We use it for faster execution and
reusable code, and it’s also applicable in assembling language programs.

b) Importance of ICT in daily life use

Information Communication Technology (ICT) plays an important role in enhancing the quality of
education. Administration and management applications of ICT are currently popular in various fields due
to its capabilities in facilitating administration activities from data storage to knowledge management and
decision making. During the last 5 decades, the world has gone through lots of changes in everyday life.
One of the most important changes that happen into humanity is ICT, which has brought a revolution in
everyday life. ICT (Information and Communication Technology) is an extended term of IT (Information
Technology) which is more focused into unified communications (real time communication services) and
integration of telecommunication. With the help of ICT, we can reduce the poverty and improve the
health and environmental condition in developing countries. Given the right approach, ICT application
can result in productivity and quality improvements. For example, in education. Information and
Communication Technology can contribute in universal access to education and deliver quality learning
and teaching. Students can learn materials as well as teacher can deliver their knowledge into students.
ICT is used in most of the fields such as E-Commerce, E-governance, Banking, Agriculture, Education,
Medicine, Defense, Transport, etc. This study aims to make daily life much easier. This study
recommends increasing awareness of internet of things role in improving activities and services in all
fields of life. It also recommends improving and processing automatic systems of different institutions
and organizations in order to comply with requirements of internet of things applications.

Q.1 a) Explain some important applications of computer.

b) Elaborate the evolution of computer system.

a) Important Applications of Computers:

1. Business and Finance:

Computers play a crucial role in managing financial transactions, accounting, payroll, and inventory
management for businesses. Financial institutions rely on computers for tasks like online banking,
electronic fund transfers, and stock market analysis. Computerized systems help streamline operations,
enhance accuracy, and facilitate efficient decision-making in the business and finance sectors.

2. Education:

Computers have transformed the field of education, enabling interactive learning experiences and
expanding access to educational resources. They are used for online learning, research, multimedia
presentations, and educational software. Additionally, computer-aided instruction and e-learning
platforms provide personalized learning opportunities for students of all ages.

3. Medicine and Healthcare:

Computers have revolutionized medical diagnostics, patient record management, and medical research.
They aid in the analysis of medical images, such as X-rays and MRIs, for accurate diagnosis. Electronic
health records (EHRs) store patient information securely and facilitate efficient healthcare delivery.
Moreover, computer simulations and modeling contribute to advancements in medical research, drug
discovery, and treatment development.
4. Communication:

Computers are integral to modern communication systems. Email, instant messaging, video conferencing,
and social media platforms rely on computer networks to connect individuals across the globe. Voice over
IP (VoIP) technology enables cost-effective and convenient voice communication. Computers also
support the transmission and storage of digital media, including music, videos, and documents.

b) Evalotions of Computer System:

1. First Generation (1940s-1950s):

The first generation of computers emerged in the 1940s and was characterized by the use of vacuum tubes
as their primary electronic component. These computers were large, expensive, and consumed a
significant amount of power. They were primarily used for scientific and military purposes. One notable
example is the ENIAC (Electronic Numerical Integrator and Computer), which was developed at the
University of Pennsylvania and used vacuum tubes to perform complex calculations.

2. Second Generation (1950s-1960s):

The second generation of computers saw the introduction of transistors as a replacement for vacuum
tubes. Transistors were smaller, more reliable, and consumed less power than vacuum tubes, resulting in
smaller and more efficient computers. This generation also witnessed the development of high-level
programming languages, such as FORTRAN and COBOL. An example of a second-generation computer
is the IBM 1401, which used transistors and magnetic core memory.

3. Third Generation (1960s-1970s):

The third generation of computers witnessed the introduction of integrated circuits (ICs), which allowed
for even greater miniaturization and increased processing power. ICs combined multiple transistors,
resistors, and capacitors onto a single chip, enabling more complex and powerful computers. The IBM
System/360 series, introduced in the mid-1960s, exemplifies third-generation computers, featuring ICs
and supporting a wide range of applications.

4. Fourth Generation (1970s-1980s):

The fourth generation of computers saw the advent of microprocessors, which integrated thousands of
transistors onto a single chip. This led to the development of personal computers (PCs) and made
computing more accessible to individuals. Microprocessors enabled faster processing speeds, improved
graphics capabilities, and increased memory capacity. The Apple II and IBM PC are prominent examples
of fourth-generation computers, revolutionizing personal computing and shaping the modern computer
industry.

Q.2 Clearly differentiates between Drum Printer and Chain Printer? Discuss with proper
examples.

Ans

Drum Printer vs. Chain Printer:

Drum Printer:

A drum printer is a type of impact printer that operates by striking a ribbon against a rotating drum with
raised characters or symbols. The drum has characters engraved or embossed on its surface, and when the
corresponding character is aligned with the paper, a hammer or print head strikes the ribbon, transferring
ink onto the paper and creating the desired print. Here are some key characteristics and examples of drum
printers:
1. Speed and Noise: Drum printers are known for their high printing speed, often surpassing other impact
printers. However, their printing process generates considerable noise, making them less suitable for quiet
office environments.

2. Examples: IBM 1403 and IBM 1443 are well-known examples of drum printers. These were
commonly used in mainframe computer systems during the 1960s and 1970s.

Chain Printer:

A chain printer, also known as a band printer, is another type of impact printer that utilizes a rotating
chain with character plates to create prints. The chain contains character plates with raised characters or
symbols, which are inked and struck against the paper to form the desired output. Here are some
distinctive features and examples of chain printers:

1. Flexibility: Chain printers are known for their flexibility in accommodating different character sets and
fonts. The character plates on the chain can be easily replaced or modified, allowing for versatile printing
options.

2. Examples: Printronix P-Series and Control Data Corporation (CDC) Chain Printer 6000 series are
notable examples of chain printers. These were commonly used in business and industrial settings, such
as printing large volumes of

invoices, reports, and other documents.

3. Quiet Operation: Chain printers generally operate more quietly than drum printers, making them
suitable for environments where noise reduction is a priority.
4. Reliability: Chain printers are known for their reliability and durability, capable of withstanding heavy
printing demands and delivering consistent output over extended periods.

In summary, drum printers and chain printers are both types of impact printers but differ in their
mechanisms and characteristics. Drum printers rely on a rotating drum with engraved characters, while
chain printers use a rotating chain with character plates. Drum printers offer high speed but generate more
noise, while chain printers are flexible, quieter, and often preferred for business and industrial printing
requirements.

Q.3 Compare features of Windows Operating System on your computer with other Operating
Systems.

ANS:

The Difference Between Operating System and Windows is An operating system (OS) is a set of
programs containing instructions that work together to coordinate all the activities among computer
hardware resources. A stand-alone operating system is a complete operating system that works on a
desktop computer, notebook computer, or mobile computing device.

Operating System:
An operating system (OS) is a set of programs containing instructions that work together to coordinate all
the activities among computer hardware resources. Most operating systems perform similar functions that
include starting and shutting down a computer, providing a user interface, managing p rograms, managing
memory, coordinating tasks, configuring devices, establishing an Internet connection, monitoring
performance, providing file management and other utilities, and automatically updating itself and certain
utility programs. Some operating systems also allow users to control a network and administer security.
Although an operating system can run from an optical disc and/or flash memory mobile media, in most
cases, the operating system is installed and resides on the computer’s hard disk. On handheld computers
and many mobile devices, the operating system may reside on a ROM chip.

Windows:
A stand-alone operating system is a complete operating system that works on a desktop computer,
notebook computer, or mobile computing device. Some stand-alone operating systems are called client
operating systems because they also work in conjunction with a server operating system. Client operating
systems can operate with or without a network. Other standalone operating systems include networking
capabilities, allowing the home and small business user to set up a small network. Examples of currently
used stand-alone operating systems are Windows 7, Mac OS X, UNIX, and Linux.
Windows 7 In the mid-1980s, Microsoft developed its first version of Windows, which provided a
graphical user interface (GUI). Since then, Microsoft continually has updated its Windows operating
system, incorporating innovative features and functions with each new version. Windows 7 is Microsoft’s
fastest, most efficient operating system to date, offering quicker program start up, built-in diagnostics,
automatic recovery, improved security, enhanced searching and organizing capabilities, and an easy-to-
use interface. Most users choose one of these Windows 7 editions: Windows 7 Starter, Windows 7 Home
Premium, Windows 7 Ultimate, or Windows 7 Professional. • Windows 7 Starter, designed for netbooks
and other small notebook computers, uses the Windows 7 Basic interface and allows users easily to
search for files, connect to printers and devices, browse the Internet, join home networks, and connect to
wireless networks. This edition of Windows typically is preinstalled on new computers and not available
for purchase in retail stores.

• Windows 7 Home Premium, which includes all the capabilities of Windows 7 Starter, also includes
Windows Aero with its Aero Flip 3D feature and provides tools to create and edit highdefinition movies,
record and watch television shows, connect to a game console, and read from and write on Blu-ray Discs.

• Windows 7 Ultimate, which includes all features of Windows 7 Home Premium, provides additional
features designed to keep your files secure and support for 35 languages.

• With Windows 7 Professional, users in all sizes of businesses are provided a secure operating
environment that uses Windows Aero where they easily can search for files, protect their computers from
unauthorized intruders and unwanted programs, use improved backup technologies, securely connect to
Wi-Fi networks, quickly view messages on a powered-off, specially equipped notebook computer, easily
share documents and collaborate with other users, and watch and record live television.
Windows 7 adapts to the hardware configuration on which it is installed. Thus, two users with the same
edition of Windows 7 may experience different functionality and interfaces.

Q.4 Write short notes on the following topics: (20)

a) Concepts of Assembler
b) Interpreter

c) Compiler

d) Linker

ANS:

a) Concepts of Assembler

An assembler is a program that takes basic computer instructions and converts them into a pattern of bits
that the computer's processor can use to perform its basic operations. Some people call these instructions
assembler language and others use the term assembly language.

Here's how it works:

 Most computers come with a specified set of very basic instructions that correspond to the basic
machine operations that the computer can perform. For example, a "Load" instruction causes the
processor to move a string of bits from a location in the processor's memory to a special holding
place called a register. Assuming the processor has at least eight registers, each numbered, the
following instruction would move the value (string of bits of a certain length) at memory location
3000 into the holding place called register 8:

L 8,3000



 The programmer can write a program using a sequence of these assembler instructions.

 This sequence of assembler instructions, known as the source code or source program, is then
specified to the assembler program when that program is started.

 The assembler program takes each program statement in the source program and generates a
corresponding bit stream or pattern (a series of 0's and 1's of a given length).

 The output of the assembler program is called the object code or object program relative to the
input source program. The sequence of 0's and 1's that constitute the object program is sometimes
called machine code.

 The object program can then be run (or executed) whenever desired.
In the earliest computers, programmers actually wrote programs in machine code, but assembler
languages or instruction sets were soon developed to speed up programming. Today, assembler
programming is used only where very efficient control over processor operations is needed. It requires
knowledge of a particular computer's instruction set, however. Historically, most programs have been
written in "higher-level" languages such as COBOL, FORTRAN, PL/I, and C. These languages are easier
to learn and faster to write programs with than assembler language. The program that processes the source
code written in these languages is called a compiler. Like the assembler, a compiler takes higher-level
language statements and reduces them to machine code.

A newer idea in program preparation and portability is the concept of a virtual machine. For example,
using the Java programming language, language statements are compiled into a generic form of machine
language known as bytecode that can be run by a virtual machine, a kind of theoretical machine that
approximates most computer operations. The bytecode can then be sent to any computer platform that has
previously downloaded or built in the Java virtual machine. The virtual machine is aware of the specific
instruction lengths and other particularities of the platform and ensures that the Java bytecode can run.

b) Interpreter

An interpreter is a computer program that is used to directly execute program instructions written using
one of the many high-level programming languages. The interpreter transforms the high-level program
into an intermediate language that it then executes, or it could parse the high-level source code and then
performs the commands directly, which is done line by line or statement by statement.

Humans can only understand high-level languages, which are called source code. Computers, on the other
hand, can only understand programs written in binary languages, so either an interpreter or compiler is
required.

Programming languages are implemented in two ways: interpretation and compilation. As the name
suggests, an interpreter transforms or interprets a high-level programming code into code that can be
understood by the machine (machine code) or into an intermediate language that can be easily executed as
well.

The interpreter reads each statement of code and then converts or executes it directly. In contrast, an
assembler or a compiler converts a high-level source code into native (compiled) code that can be
executed directly by the operating system (e.g. by creating a .exe program).

Both compilers and interpreters have their advantages and disadvantages and are not mutually exclusive;
this means that they can be used in conjunction as most integrated development environments employ
both compilation and translation for some high-level languages.
In most cases, a compiler is preferable since its output runs much faster compared to a line-by-line
interpretation. Rather than scanning the whole program and translating it into machine code like a
compiler does, the interpreter translates code one statement at a time.

While the time to analyze source code is reduced, especially a particularly large one, execution time for
an interpreter is comparatively slower than a compiler. On top of that, since interpretation happens per
line or statement, it can be stopped in the middle of execution to allow for either code modification or
debugging.

Compilers must generate intermediate object code that requires more memory to be linked, contrarily to
interpreters which tend to use memory more efficiently.

Since an interpreter reads and then executes code in a single process, it very useful for scripting and other
small programs. As such, it is commonly installed on Web servers, which run a lot of executable scripts.
It is also used during the development stage of a program to test small chunks of code one by one rather
than having to compile the whole program every time.

Every source statement will be executed line by line during execution, which is particularly appreciated
for debugging reasons to immediately recognize errors. Interpreters are also used for educational purposes
since they can be used to show students how to program one script at a time.

Programming languages that use interpreters include Python, Ruby, and JavaScript, while programming
languages that use compilers include Java, C++, and C.

c) Compiler

A compiler is a software that converts the source code to the object code. In other words, we can say that it
converts the high-level language to machine/binary language. Moreover, it is necessary to perform this step to
make the program executable. This is because the computer understands only binary language.

Some compilers convert the high-level language to an assembly language as an intermediate step. Whereas
some others convert it directly to machine code. This process of converting the source code into machine
code is called compilation. Let us learn more about it in detail.

Analysis of a Source Program

We can analyze a source code in three main steps. Moreover, these steps are further divided into different
phases. The three steps are:

1. Linear Analysis

Here, it reads the character of the code from left to right. The characters having a collective meaning are
formed. We call these groups tokens.
2. Hierarchical Analysis

According to collective meaning, we divide the tokens hierarchically in a nested manner.

3. Semantic Analysis

In this step, we check if the components of the source code are appropriate in meaning.

Phases/Structure of Compiler

The compilation process takes place in several phases. Moreover, for each step, the output of one step acts as
the input for the next step. The phases/structure of the compilation process are is follows:

1. Lexical Analyzer

 It takes the high-level language source code as the input.

 It scans the characters of source code from left to right. Hence, the name scanner also.

 It groups the characters into lexemes. Lexemes are a group of characters which has some meaning.

 Each lexeme corresponds to form a token.

 It removes white spaces and comments.

 It checks and removes the lexical errors.

2. Syntax Analyzer

 ‘Parser’ is the other name for the syntax analyzer.

 The output of the lexical analyzer is its input.

 It checks for syntax errors in the source code.

 It does this by constructing a parse tree of all the tokens.

 For the syntax to be correct, the parse tree should be according to the rules of source code
grammar.

 The grammar for such codes is context-free grammar.

3. Semantic Analyzer

 It verifies the parse tree of the syntax analyzer.

 It checks the validity of the code in terms of programming language. Like, compatibility of data
types, declaration, and initialization of variables, etc.

 It also produces a verified parse tree. Furthermore, we also call this tree an annotated parse tree.
 It also performs flow checking, type checking, etc.

4. Intermediate Code Generator (ICG)

 It generates an intermediate code.

 This code is neither in high-level language nor in machine language. It is in an intermediate form.

 It is converted to machine language but, the last two phases are platform dependent.

 The intermediate code is the same for all the compilers. Further, we generate the machine code
according to the platform.

 An example of an intermediate code is three address code.

5. Code Optimizer

 It optimizes the intermediate code.

 Its function is to convert the code so that it executes faster using fewer resources (CPU, memory).

 It removes any useless lines of code and rearranges the code.

 The meaning of the source code remains the same.

6. Target Code Generator

 Finally, it converts the optimized intermediate code into the machine code.

 This is the final stage of the compilation.

 The machine code which is produced is relocatable.

d) Linker

Linker is a program in a system which helps to link object modules of a program into a single object
file. It performs the process of linking. Linkers are also called as link editors. Linking is a process of
collecting and maintaining piece of code and data into a single file. Linker also links a particular
module into system library. It takes object modules from assembler as input and forms an executable
file as output for the loader. Linking is performed at both compile time, when the source code is
translated into machine code and load time, when the program is loaded into memory by the loader.
Linking is performed at the last step in compiling a program.
Source code -> compiler -> Assembler -> Object code -> Linker -> Executable file ->
Loader
Linking is of two types: 1. Static Linking – It is performed during the compilation of source program.
Linking is performed before execution in static linking. It takes collection of relocatable object file and
command-line arguments and generates a fully linked object file that can be loaded and run. Static
linker performs two major tasks:
LINKER DIAGRAM:

 Symbol resolution – It associates each symbol reference with exactly one symbol
definition .Every symbol has a predefined task.
 Relocation – It relocates code and data section and modifies the symbol references to the
relocated memory locations.
The linker copies all library routines used in the program into executable image. As a result, it requires
more memory space. As it does not require the presence of library on the system when it is run, so it is
faster and more portable. No failure chance and less error chance. 2. Dynamic linking – Dynamic
linking is performed during the run time. This linking is accomplished by placing the name of a
shareable library in the executable image. There are more chances of errors and failures. It require less
memory space as multiple programs can share a single copy of the library. Here we can perform code
sharing. It means if we are using the same object a number of times in the program, instead of linking
the same object again and again into the library, each module shares information of the object with
other modules having the same object. The shared library needed in the linking is stored in virtual
memory to save RAM. In this linking we can also relocate the code for the smooth running of code but
all the code is not relocatable. It fixes the address at run time.

Features :

Symbol resolution: The linker resolves symbols, such as function and variable names, across different
object files and libraries.
Relocation: The linker performs relocation, adjusting the addresses of symbols within object files and
libraries to match the final address space of the executable program.
Optimization: The linker can perform optimization, such as dead code elimination and function
inlining, to improve the performance and size of the executable program.
Library management: The linker can manage libraries, linking in only the required functions and
removing unused code to minimize the size of the executable.
Debugging information: The linker can include debugging information in the executable program,
making it easier to debug and analyze during development.
Cross-platform support: The linker can generate executable programs for different platforms,
including different architectures and operating systems.
Incremental linking: The linker can perform incremental linking, allowing changes to be made to
individual object files without needing to rebuild the entire executable program.
Versioning: The linker can support versioning of shared libraries, allowing multiple versions of a
library to coexist and preventing compatibility issues.
Link-time code generation: The linker can perform link-time code generation, allowing code to be
generated during the linking process rather than at compile time.
Linker scripts: The linker can use linker scripts, which are configuration files that specify how object
files and libraries should be linked together. Linker scripts can also be used to specify the layout of the
executable program’s memory.

Advantages of Linker

There are several advantages of using a linker in compiler design:


1. Code Reuse: A linker allows code to be reused across multiple programs by linking in shared
libraries, reducing the amount of code that needs to be written and maintained.
2. Smaller Executable Files: Dynamic linkers reduce the size of the executable file by linking
libraries at runtime, rather than including them in the executable.
3. Reduced Memory Footprint: Dynamic linkers allow multiple programs to share the same
library in memory, reducing the overall memory usage of the system.
4. Reduced Disk Space: With dynamic linking, the libraries only need to be stored on disk once,
instead of being copied into the executable of each program that uses them.
5. Improved Security: Dynamic linkers enable the use of protected libraries, which can help
prevent unauthorized access or modification of the library code.
6. Easier to Update Libraries: Dynamic linkers allow libraries to be updated or replaced without
the need to relink the program, making it easier to fix bugs, add new features, or improve
performance.

You might also like