Sie sind auf Seite 1von 68

Abstract

Very often we need short-cuts to get things done fast and to avoid confusion, and
that is the exact requirement of the programming world. Today, as programming languages grow
more sophisticated and make the life of a programmer easier, the requirements keep growing.
Programming languages perform Herculean tasks as compared to their ancestors several decades
ago. For example, from the simple days of C, companies such as Microsoft have developed much
more powerful languages such as Visual C#, which has the simplicity and foundation of C. Yet,
as we progress with the use of these languages, there are still some tools that are in use today that
make processing of code much simpler.

Code grows to such an extent today that even code needs management and
processing. In this project, we look at the processing of code before it is sent for compilation.
These tasks are called pre-processor tasks, where code is “prepared” before it is sent for
compilation. These are also known as pre-processor directives which perform a task before the
code is compiled. There are many such tools, including macro expansions. Macros are used to
make compilation easier and more feasible. We can look at the various advantages macros give
the programmer as we look at the problems inherent with coding. It should also be noted that the
subject of macros are vast and that only a few macros will be simulated. To a large extent,
macros will be designed to mimic C macros.

A macro is a piece of code or text that replaces another body of text before
compilation. These macros may or may not take parameters. In C#/C++, macros are preceded
with the “#” keyword. Therefore, code is scanned and those lines starting with the “#” symbol
are treated first and the appropriate action performed. These lines with “#” preceding them are
removed and that edited code is sent for compilation. Any compilation errors caused by macro
expansions have to be taken care of by the user. Macros can be used in a simple or complex way
to make effective use of code. A very good example is described below:

(iv)
gotoxy(10,3); //position cursor at x-axis 3 and y-axis 10
printf(“Code printed here”); //default printing function

/*This code can be replaced with the following code*/


#define DIS(y,x) gotoxy(x,y); printf //pre-processor directive
DIS(3,10) (“Code printed here”);

Here, DIS(3,10) is replaced with “gotoxy(10,3); printf” in the original source code before it is
sent for compilation. Therefore, this becomes easier if the programmer requires constant re-
positioning of cursor. The code is effectively shorter to type and much easier to read when there
are many such statements. It also becomes easier for programmers to give coordinates who are
used to providing x-asks co-ordinates first.
This is how normal macros that accept parameters work in C. These macros will be simulated in
this project.

(v)
Table of Contents

Topics Page No.

Acknowledgements iii
Abstract iv
1. Introduction
1.1. Detailed Problem Definition 2
1.2. Block Diagram 4

2. Analysis
2.1. Domain Theory of the Problem 6
2.2. SS Concept used 7
2.3. Hardware and Software Requirements 9
2.4. Description of tools used 9

3. System Design
3.1. Modular Design 11
3.2. Detail for each Module 13
3.3. Input Specifications 17
3.4. Output Specifications 17

4. Implementation
4.1. Screen Shots 22
4.2. Sample Code 26

5. Testing
5.1. Test Cases 44
5.2. Test Reports 45

6. Conclusion
6.1. Advantages and Disadvantages 48
6.2. Future Enhancements 49

References
Appendix A (Macros) 51
Appendix B (C# Programming) 62
Bibliography 65
Macro Processor for C/C++

Chapter – 1
INTRODUCTION

Department of Computer Science (MCA), Christ University 1


Macro Processor for C/C++

1.1. Problem Definition

Processing of source code for a compiler requires many tasks before actual
compilation of the program. Most of theses tasks require refinement of code for the
machine to understand. Programmers may write code to the best possible extent of their
understanding and simplicity. Therefore, this requires a translation to more extensive
code that the compiler can understand. Some of the problems faced by programmers in
writing extensive code are explained in detail in the next few paragraphs.

Code Readability: Very often while writing large chunks of code, there may be many
places where code is repeated. Repetition of code can lead to confusion and reduce the
readability of code. Maintaining readability is one of the main essences of proper
programming. It also is the most difficult of tasks. Even with sufficient comments and
spacing, it can still be hard to maintain readability. Furthermore, it is hard for humans to
understand the same level of instructions as programming languages. The balance
between human understanding and mnemonics is often blurred. It would be feasible for
the programmer to replace large chunks of repeated code with a single “code” that has the
same meaning. This would improve readability to a great extent and help with debugging
purposes too. However, replacement text can sometimes cause more confusion if the
programmer does not properly handle them.

Function Overhead: Functions help solve this problem by sorting relevant code into
one area. A program in sequence can call such a function, make it perform its task and
return control to the line following the function call. However, functions (or methods)
have a large overhead and can waste valuable processor time by repeatedly calling the
same function. In fact there is nothing wrong with repeated code for the compiler. If the
program execution requires repeated execution of codes, then functions will cause a

Department of Computer Science (MCA), Christ University 2


Macro Processor for C/C++
significant loss of performance, especially if the functions carry small amounts of code in
them. Therefore, functions should not be used to hold replacement code, but to hold
relevant code that needs to be called only when required.

Increased Processor Time: As already mentioned, repeated codes and calls for
replacement can cause considerable processor wastage. Processing time is an important
component of any system software. Applications can afford to suffer from processing
time, but if system software largely suffers from processing time, then the whole setup is
affected. Macros may increase compilation time by replacing text, including more text
and submitting partial parts for compilation, but they help in producing more reliable
code.

Increased Spaghetti Code: The use of functions and redirection of control to other
places to perform repeated functions results in what is called “spaghetti code”. This kind
of code is rampant in the older top-bottom approach of programming languages, where
instructions appear in sequence. Object-oriented programming techniques remove
spaghetti code problems, but can only be implemented on object-oriented platforms.
Moreover, even OOP concepts still suffer from readability problems. Programming
languages such as C, where spaghetti code is all but common; macros can help reduce
this problem

Compilation Issues: To increase readability of code, often, methods are written in


various files and included wherever necessary. Unfortunately, these individual files
cannot be compiled and then included during linking and execution. Therefore, this
approach cannot be used unless macros are used to include the text from these files in the
main source code file. This improves readability, reliability and debugging of the entire
project.

Department of Computer Science (MCA), Christ University 3


Macro Processor for C/C++

1.2. Block Diagram

The following is a block representation of the various actions that will take
place for a fully-processed file with macros expanded and removed.

Input file

Scan file for macros


Macro
names
Extract macros with
Macro name and definition
definitions

Scan for macro names

Replace macro name


with corresponding definition

Processed
file
Fig
1.a. Block representation of macro expansion

Department of Computer Science (MCA), Christ University 4


Macro Processor for C/C++

Chapter – 2
ANALYSIS

Department of Computer Science (MCA), Christ University 5


Macro Processor for C/C++

2.1. Domain Theory of the Problem


The project involves the use of macros to help programmers write better
and more readable code. This task is a pre-processor task and does not result in
compilation of code, but is a step prior to compilation. The following are a set of domains
that macro processing touch upon. Some of these fields may not be largely involved with
macros, but contain generic concepts that largely affect systems programming. Systems
software are more concerned with tasks that help with the reduction of processing time
and overheads. Therefore macros help with the following

9 Less use of functions for calling repeated code


9 Less overhead when less functions are used
9 Reduced processing time. (Although, code may be repeated, it is required and is
not redundant. Therefore, the source code remains efficient)
9 Programming tool that is vastly used
9 Helps reduce spaghetti code and ultimately makes code more readable.
9 Helps with the use of variables even in repeated code. Similar to parameters for
functions, but without the overhead
9 Replaces text in code as the user wished and contains no references nor pointers
9 Usage of pre-processing tools that prepare source code for compilation
9 Conditional compilation depending on certain system architecture and
requirements
9 Providing dynamic and variable values to static chunks of text that require
replacement. (For example, the usage of #define with parameters that replaces
chunks of code with different values passed to it). This is performed without the
problem of programming overhead caused by the repeated use of functions.

Department of Computer Science (MCA), Christ University 6


Macro Processor for C/C++

2.2. SS Concept Used


As already mentioned, there are many concepts associated with the concept
of systems software. Some of the concepts used in this project are as follows:

Macros
A macro, as already mentioned, is an abbreviation for a sequence of
operations. Macros are used to replace text and help solve problems such as readability
and simplicity. In primitive assembly code, macros are defined by two instructions the
MACRO and MEND instruction. A macro operation permits writing a sequence of
assembly instructions and to using its name in to replace it. A macro processor is by itself
a language processor with its own syntax and rules. The general form of writing a macro
in assembly language is
MACRO <macro-name>
//Body of the macro
MEND

Therefore, the keyword “MACRO” is an indication of a start of a macro and the


following text is the name of the macro. This is required for storage and retrieval of
macros. The MEND is an indication of the macro. In more sophisticated languages such
as C#/C++, the MACRO keyword may be replaced by the “#” symbol and the <macro-
name> with the text that follows. The body of the macro is the text that follows the name
and the MEND is indicated by a newline character ‘\n’.

Here’s a typical example of how macros work in assembly language


mnemonics. This is a simple macro which takes no parameters
MACRO SUB
S 3,DATA
S 4,DATA
Department of Computer Science (MCA), Christ University 7
Macro Processor for C/C++
MEND
In the main program, the usage of the word SUB explicitly replaces that
text with the text that appears between the macro-name SUB and MEND. When the code
is submitted for compilation, it will not have the macro call within it and in fact will
resemble as though the user had placed the text there himself. This operation is
performed by the macro-processor. This task can therefore save considerable typing and
improve readability of code to a large extent. The same example can be applied to
existing high-level languages where a macro like LOOP j (1 to 5) can be used instead of
for (j=0; j<=5; j++)

Macros can do more than just replace text where it is required. Some of the
additional features of macros are as follows:
9 Macros can take parameters whose values can be replaced within the macro
expansion. This makes macro usage more dynamic
9 Macros can be used to conditionally include code depending on some condition.
This is useful for codes which may vary on different architectures.
9 Macros that exist within a macro (recursive calls of macros)

Lexical Analyser
Although this is not part of the scope of the project, it was required here
and there to understand the boundary of the macro calls. It was important to know the
sequence of tokens to know when a macro may start and end. To limit the use of lexical
analysing concepts, macro calls in the main source code are surrounded by user-defined
characters such as ‘@’. Therefore, a complete and exact simulation of macro calls in
C#/C++ was not possible as the realm of lexical analysis was necessary to achieve this
task.

Department of Computer Science (MCA), Christ University 8


Macro Processor for C/C++

2.3. Hardware and Software Requirements


The hardware and software requirements for this project are limited to only
the requirements of a C compiler on a UNIX or Windows machine.

Hardware Requirements
9 Pentium 60 MHz or higher
9 8 MB RAM or higher
9 10 MB hard-disk space free (not including swap space required for the OS)

Software Requirements
9 Borland Turbo C compiler or any other version compatible with IO streams
9 Windows 98 or later
9 Implementable on UNIX OS with minor adjustments

2.4. Description of Tools used

Microsoft Visual C#.Net is used for developing front end for this project. C# is a multi-
paradigm programming language encompassing imperative, functional, generic, object-
oriented (class-based), and component-oriented programming disciplines. It was
developed by Microsoft within the .NET initiative and later approved as a standard by
Ecma (ECMA-334) and ISO (ISO/IEC 23270). C# is one of the programming languages
designed for the Common Language Infrastructure.

C# is intended to be a simple, modern, general-purpose, object-oriented programming


language. Its development team is led by Anders Hejlsberg. The most recent version is
C# 3.0, which was released in conjunction with the .NET Framework 3.5 in 2007. The
next proposed version, 4.0, is in development.

Department of Computer Science (MCA), Christ University 9


Macro Processor for C/C++

Chapter – 3
SYSTEM DESIGN

Department of Computer Science (MCA), Christ University 10


Macro Processor for C/C++

3.1. Modular Detail

The project is largely divided into two major modules. The logic followed
is that of a two-pass processor. The first pass scans for macros and makes an entry of
macros found that will be found in the main source code. The second pass scans for
replacement of macros in the main source code. Within these modules, it can be further
broken down to smaller modules for better understanding and refinement.

First Pass
The first pass, as already stated carries out the scanning of macros.
Algorithm 3.2 (a) shows the overall working of this module. There are a lot more cases
and validations that occur in this module than that depicted in figure 3.2.(a). The kind of
macros used here are simple, one-line macros that have their beginning indication with
the symbol ‘#’ and the termination with the newline character ‘\n’. Therefore, if a
newline is encountered before the macro name and definition, then the macro has pre-
maturely ended. Such encounters should not stop the pre-processing work, but merely
highlight the programmer that there are errors with macro declarations. Errors which are
overlooked are taken care of in the next pass. The first pass module has the following
features:

Error-checking: Errors are highlighted to the programmer when required, else rectified
as much as possible. For example, whitespaces are generally never considered as part of
the compilation routine. Therefore, the following routine is followed:
# <macro-directive> <macro-name> <macro-definition> ¬

File Preparation: Macros are found and reported as successful and the input program is
stored into a different files without the macros. The macro names and the definitions are
stored in a structure. As error-checking continues, two variables that hold the values for
Department of Computer Science (MCA), Christ University 11
Macro Processor for C/C++
the macro name and macro definition. Files are a better option as the number of macros
might be large. Arrays would not be suitable to hold these values as handling character
arrays in C are highly sensitive and resource-consuming. Therefore, entries for macros
should not be written to files, if there are any errors during the scanning of that particular
macro.

Second Pass
The second pass is concerned with replacing macros and removing their
definitions as they are not tokens that do not make sense to the compiler. Algorithm 3.2
(b). gives an idea of the working of this module. However, there are more background
processes that run, which complete the process of replacing macros and preparing the
final source code. The second pass module has the following features:

Error-Checking: Whitespaces are once again a common programming error which


should not stall the compilation process. Therefore, once a macro name is encountered,
the scanning should begin once the whitespaces end. Other minor errors should be seen to
and reported and by-passed if possible.

Scanning for keywords: For the design of macro processor in this project, there are two
keywords that require actions to be performed. The first keyword is the ‘#’ symbol. This
symbol can mean two things—a macro definition or a conditional macro directive.
Therefore, the macro directive following the ‘#’ symbol should be scanned to determine
what action is to be performed.

Macro Expansion: This is the obvious part of the pre-processing task. Since the macro
names and the corresponding macro definitions are stored in the structure the expansion
is just replacing the macro names with its definition. If no macro name exists for the
keyword found, then the error should be highlighted and the text should be maintained as
it is. If the macro name is invalid, then it is possible that text woulds require being output
Department of Computer Science (MCA), Christ University 12
Macro Processor for C/C++
as it is. This can happen in printf statements. However, if the macro name does exist, the
corresponding definition should be replaced as it is.

File Preparation: In the end, the output of the program should be a C file that is ready
for compilation. The final file should be free of all macro directives such as the ‘#’
symbol. Most importantly, is that all handlers and resources should be released. The new
file created should have the extension .c.

3.2. Details of Module


Project is implementing 2 pass Macro processor. Basic working of Passes
are as follows:
Pass I
• Examine every operation code

• Save all macro definitions in a MDT( Macro Definition Table)

• Save a copy of the input text, minus macro definitions on secondary storage for
use in pass II

• Prepare a Macro Name table(MNT)

Pass II

• Examine every string in program

• Replace each macro name with the appropriate text from the macro definition.

3.2 (a) Algorithm Pass 1

1. Search for # define construct

2. Enter Macro name and type in MNT

3. Enter Macro Definition in MDT

Department of Computer Science (MCA), Christ University 13


Macro Processor for C/C++
4. Enter Start and end index of MDT in MNT

3.2 (b) Algorithm Pass 2

1) Read string from source code till a break character is found : S1


2) Search S1 in MNT
If found then
Take type, argc from MNT : TT, argc
If tt=”O” || argc=0
Obtain start, ending index from MNT entry
For i=start to end
Extract MDT[i]
Extract Body column B1
Copy B1 to destination file
Set pointer to next line
End for
Copy break character to destination file
Else
Argtc=0
I=1
While ch = “)”
Read ch from file
While not ch= “,”
Str=str+ch
End while
Set argt[i]=str
Read next ch
End while
For i=start to end
Extract MDT[i]

Department of Computer Science (MCA), Christ University 14


Macro Processor for C/C++
Extract Body column B1 :str1
If there is no # in str1
Copy B1 to destination file
Set pointer to next line
Else
Finalstr=nul
I=0
While i<str.length
if str[i] = #
{
read in next string till u get non numeric
character; str2
get value from argt[str2] : val1
finalstr=finalstr+val1
i=str2.length+i+1;
}
Else
{
Finalstr=finalstr+str[i];
I++
}
Copy finalstr to destination file
Set pointer to next line
End for

Else
Copy to destination file + Break character.

Department of Computer Science (MCA), Christ University 15


Macro Processor for C/C++
Flowchart for PASS 1:

Department of Computer Science (MCA), Christ University 16


Macro Processor for C/C++
Flowchart for PASS 2:

3.3 Input Specification


Valid C/C++ source code in file with .c or ,cpp extention.

3.4 Output Specification


Code will be generated with expansion of Macros and without macro definitions. Various
data structures will be used for processing. These data structure will also be provided as
an output. The various data structures used and their format are as follows:
Pass I:
1. The Input macro source deck.

Department of Computer Science (MCA), Christ University 17


Macro Processor for C/C++
2. MDT, used to store the macro definitions.

3. MNT, used to store the names of the macro definitions.

4. ALA (Argument List Array), to substitute index markers for dummy args. Before
storing the macro def.

Pass 2:.

1. The output expanded source deck to be used as input to the assembler.

2. MDT and MNT created by Pass I.

3. ALA ( Argument List Array), to substitute macro call arguments for the index
markers in the stored macro definition.

MACRO NAME TABLE (MNT)

Field name Description

mnt_index Index to macro name

Mnt_name Macro name

Mnt_type Type of macro-


ƒ o-object type macro

ƒ f-function type macro

Mdt_startindex Starting index of the macro body in macro definition table

Mdt_endindex End index of the macro body in macro definition table.

¾ The macro name table is used to store the information related to macro.

Department of Computer Science (MCA), Christ University 18


Macro Processor for C/C++
¾ When a macro name is encountered it is added to MNT

¾ Macro type is found i.e. either object type(o) or function type(f) and is added to
MNT .

¾ The starting index(mdt_index) of macro body in MDT is added to MNT

¾ The end index of macro body in MDT is also added to MNT

MACRO DEFINITION TABLE (MDT)

Field name Description

mdt_index Index of the macro definition

mdt_body Contains the body of macro definition which is


expanded when the call to macro is made.
Here the arguments are stored using positional
parameters; the arguments are given number according
to the way they appear in argument list.
Example-#1-denoted 1st argument

¾ The macro definition table is used to store the body of each macro defined.

¾ When the macro definition (#define) is found during scanning, the respective body
of the macro defined is stored in MDT.

¾ This macro definition table is also referred when a macro call is encountered.
During this the body of the macro is obtained from MDT and is expanded.

¾ It is a temporary table and is used during every preprocessing.

Department of Computer Science (MCA), Christ University 19


Macro Processor for C/C++

ARGUMENT LIST TABLE (ARGT)

Field name Description

Arg_index Index of the argument

Arg_name Argument Name which can be either


ƒ arguments part of Macro Definition

ƒ arguments part of macro call

There are two use of argument list table


¾ During macro definition- when macros with arguments are obtained, each
argument is added to the ARGT using positional parameter notation.

When the macro body is added to the MDT, during that time, if argument is
present, then it is replaced by its index prefixed with # (eg. #1 represents 1st
argument).
¾ During macro call- when macro with arguments is called then all the arguments
are put to the ARGT in the sequence they appear.

When the macro body is added to the MDT, during that time, if positional
parameters (e.g. #1) are obtained then they are replaced using ARGT.

Department of Computer Science (MCA), Christ University 20


Macro Processor for C/C++

Chapter – 4
IMPLEMENTATION

Department of Computer Science (MCA), Christ University 21


Macro Processor for C/C++

4.1 Screen Shots

Department of Computer Science (MCA), Christ University 22


Macro Processor for C/C++

Department of Computer Science (MCA), Christ University 23


Macro Processor for C/C++

Department of Computer Science (MCA), Christ University 24


Macro Processor for C/C++

Department of Computer Science (MCA), Christ University 25


Macro Processor for C/C++

4.2 Sample Code


richTextBox1.Text = "";
SourceCode.Items.Clear();
macrolist.Items.Clear();
Com_module.ff2.listBox1.Items.Clear();
int key;
string str, temp, str11;
char cc;
ArrayList colorcc = new ArrayList();
int cccount = 0;
int ii = 0, pp = 0, pt = 0, j, k, argtf = 0, acount = 0;
int mdtc = 0, mntc = 0, macroflag = 0;
DataTable mnt = new DataTable();
int mntind, start = 0, argtc = 0;
int mdtps = 0, mdtpe = 0;
int stringiflag = 0;
string name = null, type = null, tstr = null, fstr = null;
Hashtable argt = new Hashtable();
mnt.Columns.Add("Index", typeof(int));
mnt.Columns.Add("Name", typeof(string));
mnt.Columns.Add("Type", typeof(string));
mnt.Columns.Add("start", typeof(int));
mnt.Columns.Add("end", typeof(int));
mnt.Columns.Add("Argc", typeof(int));

string str1 = null, temp1;


DataTable mdt = new DataTable();
mdt.Columns.Add("Index", typeof(int));
mdt.Columns.Add("Body", typeof(string));
OpenFileDialog ftp = new OpenFileDialog();

Department of Computer Science (MCA), Christ University 26


Macro Processor for C/C++
ftp.Title = "C++ Files";
ftp.Filter = "All C++ File (*.cpp)|*.cpp";
if (ftp.ShowDialog() == DialogResult.Cancel)
return;
filetext.Text = ftp.FileName;
FileStream fs1 = new FileStream(filetext.Text, FileMode.Open, FileAccess.Read);
StreamReader sourcesr = new StreamReader(fs1);
while (sourcesr.Peek() != -1)
{
argtc = 0;
acount = 0;
argtf = 0;

str = null;
argt.Clear();
str1 = null;
temp = null;
temp1 = null;
str = sourcesr.ReadLine();
if (str == "")
continue;
temp = str;
SourceCode.Items.Add(str);
if (temp[0] == '#' && temp[1] == 'd' && temp[2] == 'e' && temp[3] == 'f' && temp[4]
== 'i' && temp[5] == 'n' && temp[6] == 'e')
{

if (temp[7].ToString() == " ")


{
for (j = 8; temp[j].ToString() == " "; j++)
{

Department of Computer Science (MCA), Christ University 27


Macro Processor for C/C++

temp1 += temp[j];
}
for (; temp[j].ToString() != " " && temp[j].ToString() != "("; j++)
{

str1 += temp[j];
}
name = str1;
macroflag = 1;
macrolist.Items.Add(str1);
if (temp[j].ToString() == " ")
{
type = "O";
acount = 0;
start = mdtc + 1;
do
{
str1 = null;
for (; j < temp.Length && temp[j].ToString() != "\\"; j++)
{
str1 += temp[j];
}
mdtc = mdtc + 1;
mdt.Rows.Add(mdtc, str1.Trim());
if (j < temp.Length)
{
temp = null;
temp = sourcesr.ReadLine();
SourceCode.Items.Add(temp);
j = 0;

Department of Computer Science (MCA), Christ University 28


Macro Processor for C/C++
//mdt.Rows.Add(mdtc, str1);

}
} while (j == 0);

}
else if (temp[j].ToString() == "(")
{
acount = 0;
type = "F";
j++;
start = mdtc + 1;
str = null;
if (temp[j].ToString() != ")")
{
while (temp[j - 1].ToString() != ")")
{
if (temp[j].ToString() == "," || temp[j].ToString() == ")")
{
if (str.Trim() != "")
{
argtf = 1;
argtc = argtc + 1;
argt.Add(argtc, str);
str = null;
acount = acount + 1;
}
}
else
{

Department of Computer Science (MCA), Christ University 29


Macro Processor for C/C++
str += temp[j];
}
j++;
}
Com_module.ff2.listBox1.Items.Add("");
Com_module.ff2.listBox1.Items.Add("Macro -> " + name);
for (int a = 1; a <= argt.Count; a++)
{
Com_module.ff2.listBox1.Items.Add(a + " -> " + argt[a]);
}
}
else
{
j++;
}
do
{

str1 = null;
for (; j < temp.Length && temp[j].ToString() != "\\"; j++)
{
str1 += temp[j];
}
if (argtf == 1)
{
temp1 = null;
temp1 = str1.Trim() + "\\";
str1 = null;
str = null;
for (k = 0; k < temp1.Length; k++)
{

Department of Computer Science (MCA), Christ University 30


Macro Processor for C/C++

if (IsAlpha(temp1[k].ToString()) == false &&


IsInteger(temp1[k].ToString()) == false)
{

if (argt.ContainsValue(str) == true)
{

for (int a = 1; a <= argt.Count; a++)


{
if (argt[a].ToString() == str)
{
str = "@" + a.ToString();
}
}
}

str1 = str1 + str + temp1[k];


str = null;

}
else
{
str += temp1[k];
}
}

Department of Computer Science (MCA), Christ University 31


Macro Processor for C/C++
}

mdtc = mdtc + 1;
mdt.Rows.Add(mdtc, str1.Trim(' ', '\\'));
if (j < temp.Length)
{
temp = null;
temp = sourcesr.ReadLine();
SourceCode.Items.Add(temp);
temp = temp.Trim();
j = 0;
}
} while (j == 0);
}

mntc = mntc + 1;
mnt.Rows.Add(mntc, name, type, start, mdtc, acount);

}
}
}

Com_module.ff.dataGridView1.DataSource = mdt;
Com_module.ff1.dataGridView1.DataSource = mnt;
if (macroflag == 1)
{
stringiflag = 0;
FileStream fs2 = new FileStream(filetext.Text, FileMode.Open, FileAccess.Read);

Department of Computer Science (MCA), Christ University 32


Macro Processor for C/C++
StreamReader sour = new StreamReader(fs2);
while (sour.Peek() != -1)
{
str = null;
stringiflag = 0;
str = sour.ReadLine();
if (str == "")
continue;
temp = str;
if (temp[0] == '#' && temp[1] == 'd' && temp[2] == 'e' && temp[3] == 'f' &&
temp[4] == 'i' && temp[5] == 'n' && temp[6] == 'e')
{
do
{
j = temp.Length;
j = j - 1;
if (temp[j] == '\\')
{
temp = sour.ReadLine();
continue;
}
} while (temp[temp.Length - 1] == '\\');

}
else
{
j = 0;
key = 0;
temp = str;
str1 = null;
str = null;

Department of Computer Science (MCA), Christ University 33


Macro Processor for C/C++
temp.Trim();
for (k = 0; k < temp.Length; k++)
{
key = 0;
if (temp[k] == '"')
{
str = str + temp[k].ToString();
do
{
k++;
str = str + temp[k].ToString();
} while (temp[k] != '"');
k++;
}
if (IsAlpha(temp[k].ToString()) == false && IsInteger(temp[k].ToString()) ==
false)
{
for (j = 0; j < mnt.Rows.Count; j++)
{
if (mnt.Rows[j][1].ToString() == str)
{
mdtps = int.Parse(mnt.Rows[j][3].ToString());
mdtpe = int.Parse(mnt.Rows[j][4].ToString());
key = 1;
name = str;
acount = int.Parse(mnt.Rows[j][5].ToString());
type = mnt.Rows[j][2].ToString();
}
}
if (key == 1)
{

Department of Computer Science (MCA), Christ University 34


Macro Processor for C/C++
if (type == "O")
{
str = null;
for (j = mdtps - 1; j <= mdtpe - 1; j++)
{
str = null;
if (j > mdtps - 1)
{
richTextBox1.Text = richTextBox1.Text + "\n";

str = str + mdt.Rows[j][1];


richTextBox1.Text = richTextBox1.Text + str;
colorcc.Add(richTextBox1.Text.Length - str.Length);
colorcc.Add(str.Length);
colorcc.Add(Color.HotPink);
cccount = cccount + 3;

//richTextBox1.Select(richTextBox1.SelectionStart, str.Length);
//MessageBox.Show(richTextBox1.SelectionStart.ToString() );
//MessageBox.Show(richTextBox1.SelectionLength.ToString());
richTextBox1.SelectionColor = Color.BlueViolet;
}

richTextBox1.Text = richTextBox1.Text + temp[k].ToString();


}
if (type == "F")
{
str = null;

Department of Computer Science (MCA), Christ University 35


Macro Processor for C/C++
str1 = null;
argt.Clear();
for (int i = 0; i < acount; i++)
{
argt.Add(i, "");
k++;
while (temp[k] != ',' && temp[k] != ')')
{
argt[i] = argt[i] + temp[k].ToString();
k = k + 1;
}

}
while (temp[k - 1] != ')')
{
k = k + 1;
}
if (acount == 0)
{
str = null;
for (j = mdtps - 1; j <= mdtpe - 1; j++)
{
str = null;
if (j > mdtps - 1)
{
richTextBox1.Text = richTextBox1.Text + "\n";

str = str + mdt.Rows[j][1];


richTextBox1.Text = richTextBox1.Text + str;

Department of Computer Science (MCA), Christ University 36


Macro Processor for C/C++
colorcc.Add(richTextBox1.Text.Length - str.Length);
colorcc.Add(str.Length);
colorcc.Add(Color.Brown);
cccount = cccount + 3;

//richTextBox1.Select(richTextBox1.SelectionStart, str.Length);
//MessageBox.Show(richTextBox1.SelectionStart.ToString() );
//MessageBox.Show(richTextBox1.SelectionLength.ToString());
richTextBox1.SelectionColor = Color.BlueViolet;
}

richTextBox1.Text = richTextBox1.Text + temp[k].ToString();

}
else
{
str = null;
stringiflag = 0;
for (j = mdtps - 1; j <= mdtpe - 1; j++)
{
str1 = null;

fstr = null;
str = null;
if (j > mdtps - 1)
{
richTextBox1.Text = richTextBox1.Text + "\n";

Department of Computer Science (MCA), Christ University 37


Macro Processor for C/C++
str = mdt.Rows[j][1].ToString();
if (str.IndexOf("##") >= 0)
{
string str111 = null;
int kkk = str.IndexOf("##");
for (int iii = 0; iii < kkk; iii++)
str111 = str111 + str[iii].ToString();
for (int iii = kkk + 2; iii < str.Length; iii++)
str111 = str111 + str[iii].ToString();
str = str111;
}

for (ii = 0; ii < str.Length; ii++)


{
fstr = null;
stringiflag = 0;
if (str[ii] == '#')
{
if (str[ii + 1] == '@')
{
ii++;
stringiflag = 1;
}
}
if (str[ii] == '@')
{

while (ii < str.Length - 1 && IsInteger(str[ii + 1].ToString())


== true)
{

Department of Computer Science (MCA), Christ University 38


Macro Processor for C/C++
fstr = fstr + str[ii + 1];
ii = ii + 1;

}
pp = int.Parse(fstr);
if (stringiflag == 0)
{

str1 = str1 + argt[pp - 1].ToString();


}
else
{
str11 = argt[pp - 1].ToString();
string strs = null;

for (int sst = 0; sst < str11.Length; sst++)


{
if (str11[sst].ToString() == "\"")
{
if (sst == 0)
{
strs = strs + "\\";
}

strs = strs + str11[sst];

}
else
{
if (sst + 1 < str11.Length && str11[sst + 1].ToString()
== "\"")

Department of Computer Science (MCA), Christ University 39


Macro Processor for C/C++
{
strs = strs + str11[sst];

strs = strs + "\\";

}
else
{
strs = strs + str11[sst];
}

}
}
strs = "\"" + strs + "\"";
str1 = str1 + strs;
//str1 = str1 + "\"" + argt[pp - 1].ToString() + "\"";
}
}
else
{
str1 = str1 + str[ii];
}
}

richTextBox1.Text = richTextBox1.Text + str1;


colorcc.Add(richTextBox1.Text.Length - str1.Length);
colorcc.Add(str1.Length);
colorcc.Add(Color.Green);
cccount = cccount + 3;

Department of Computer Science (MCA), Christ University 40


Macro Processor for C/C++
//richTextBox1.Select(richTextBox1.SelectionStart, str.Length);
//MessageBox.Show(richTextBox1.SelectionStart.ToString() );
//MessageBox.Show(richTextBox1.SelectionLength.ToString());

richTextBox1.Text = richTextBox1.Text + temp[k].ToString();


}
}

}
else
{
richTextBox1.Text = richTextBox1.Text + str + temp[k].ToString();
}
//str1 = str1 + str + temp[k].ToString();
str = null;
}
else
{
str = str + temp[k].ToString();
}

}
// richTextBox1.Text = richTextBox1.Text + str1+"\n";
richTextBox1.Text = richTextBox1.Text + "\n";

Department of Computer Science (MCA), Christ University 41


Macro Processor for C/C++
}
for (j = 0; j < cccount; j = j + 3)
{
richTextBox1.SelectionStart = int.Parse(colorcc[j].ToString());
richTextBox1.SelectionLength = int.Parse(colorcc[j + 1].ToString());
richTextBox1.SelectionColor = (Color)colorcc[j + 2];
}
}

Department of Computer Science (MCA), Christ University 42


Macro Processor for C/C++

Chapter – 5
TESTING

Department of Computer Science (MCA), Christ University 43


Macro Processor for C/C++

5.1. Test Cases

The following test plans were put into effect and carried out:

Basic Validation: This requires that the input file exist before being processed. The
name of the file is input is given as a parameter with the execution of the program. If the
filename provided as input is invalid or doesn’t exist in the current directory, the program
terminates and reports that the file doesn’t exist or cannot be opened.

Names of Directives: For macro saving, only #define macros are taken care of. The
other macros are seen as errors for the first pass, but may be valid for the next pass. The

Department of Computer Science (MCA), Christ University 44


Macro Processor for C/C++
program highlights all other directives that are not #define as possible errors and may
require rectification. The directives that do not match are enclosed in *** along with the
line number to bring it to the attention of the programmer. During, macro expansion,
directives that are not of the conditional compiling type are ignored and the line
completely skipped and not included in the final source code. This is because other
directives may have been valid directives that were successfully expanded or raised as
errors in the first pass. Either way, these lines should not be included in the final source
code. Care should be taken by the programmer to not include parts of the intended source
code in the same line as a pre-processor directive.

5.2. Test Reports

During the implementation of the program, there were many small


programs setup to ensure that the proper testing methods were used. Since the application
is divided into largely two modules, it is necessary to test the operation and results of
each module. For software testing, thorough verification of code and repeated executions
with various scenarios and data are tested. Logical verification by flow of data has to be
determined as early as possible, so that rectification of code can be done easily. The
corresponding output values for each module are confirmed and changes made in
correspondence with the output observed. For example, each module was individually
designed to suit the requirements of that module. The scanning module contained only
those details that were relevant to it. All operations for that module were tested and
checked individually. Modules with the least functional dependencies can be designed
first, so that they can be used by the more complex data dependencies which may have
references to it. From the very design of the project, the functionality was seen as several
modules that could exist by passing certain data amongst themselves when required. For
unit testing, the data that was required from other modules were either provided by the
other module directly, if already designed or were provided with dummy values (stubs)
that could act as potential values that could be passed to it. For this error-handling,
Department of Computer Science (MCA), Christ University 45
Macro Processor for C/C++
procedures were setup to ensure that it could collect only data that was required by it. The
very design of the program often ensured that only correct values may be passed when
required.
The application is complete only if the modules are working in tandem.
Hence, after the individual modules are tested, it is imperative to perform the integration
test. An interface between the modules is necessary. In this application, there is some
interface between modules. For example, the input file name is required for the second
pass scan, which it receives from the result of the first pass. It was important to note the
difference between data that arrived during an execution of a function.

Department of Computer Science (MCA), Christ University 46


Macro Processor for C/C++

Chapter – 6
CONCLUSION

Department of Computer Science (MCA), Christ University 47


Macro Processor for C/C++

6.1. Advantages and Disadvantages

The following are the major advantages of the project

9 Effectively replaces code that was meant for replacement with the help of macros.
9 Used concepts such as file pointers, structures to carry out its tasks
9 Highlights errors caused by macros that the programmer can rectify before the
code is sent for compilation rather than to be intimated of errors during
compilation.
9 Produces the output file, even if there are errors or warnings in the input file.
9 Maintains a separate input file and a separate output file for data verification and
rectification.
9 Maintains macro names and their definitions in structures, thereby reducing the
amount of resources involved with character arrays and is useful for debugging
purposes.
9 Tabs and whitespaces and original contents of the input file are maintained as they
are even in the final source code file.

The following are the major disadvantages of the project

x Conditional macros are not taken care only simple macros, parameterized macro,
macro within macros are taken care off.
x The input file has to be prepared as a text file, which means the programmer will
have to first save his program as a .txt file. Also, the output file is created as a .txt
file, which means the programmer will have to bring this output file back to the
IDE for compilation. Compilation errors would require the programmer to start the
process from scratch

Department of Computer Science (MCA), Christ University 48


Macro Processor for C/C++

6.2. Future Enhancements

Based on the development of the project, there is sufficient scope for


further enhancement. Enhancements can be made by way of improving on existing
features, addition of new features, removal of constraints and increasing flexibility to
macros. Some of the possible future enhancements are as follows:

Taking care of conditional macros


Conditional macros like the #if, #unif, #ifdef, #elif, #else are not taken into
account in

Inclusion of a compiler
Steps can be taken to develop an IDE (Integrated Development
Environment), so that the output cpp file can be directly compiled and the results caused
due to macro expansions can be taken care of. However, the development of an IDE
would require also the development of an editor, a parser, linker and other systems
software concepts that are well beyond the boundaries of a simple macro processor.
However, with the combination of a compiler, the use of macros can be fully justified.

User-defined macros
User-defined macros can be setup to help programmers work with arrays
and files better. These macros can be used to perform regular tasks such as arranging
elements in ascending or descending order, or to open files with a given filename and file
mode. These specifics can be applied with more input from the programmer as to how he
would like to lessen the amount of typing and to help increase readability.

Department of Computer Science (MCA), Christ University 49


Macro Processor for C/C++

REFERENCES

Department of Computer Science (MCA), Christ University 50


Macro Processor for C/C++

Appendix A (Macros)

Macros

A macro is a sort of abbreviation which you can define once and then use later. There are
many complicated features associated with macros in the C preprocessor.

Simple Macros

A simple macro is a kind of abbreviation. It is a name which stands for a fragment of


code. Some people refer to these as manifest constants.

Before you can use a macro, you must define it explicitly with the `#define' command.
`#define' is followed by the name of the macro and then the code it should be an
abbreviation for. For example,

#define BUFFER_SIZE 1020

defines a macro named `BUFFER_SIZE' as an abbreviation for the text `1020'.


Therefore, if somewhere after this `#define' command there comes a C statement of the
form

Macros with Arguments

A simple macro always stands for exactly the same text, each time it is used. Macros can
be more flexible when they accept arguments. Arguments are fragments of code that you
supply each time the macro is used. These fragments are included in the expansion of the
macro according to the directions in the macro definition.

To define a macro that uses arguments, you write a `#define' command with a list of
argument names in parentheses after the name of the macro. The argument names may be

Department of Computer Science (MCA), Christ University 51


Macro Processor for C/C++
any valid C identifiers, separated by commas and optionally whitespace. The open-
parenthesis must follow the macro name immediately, with no space in between.

For example, here is a macro that computes the minimum of two numeric values, as it is
defined in many C programs:

#define min(X, Y) ((X) < (Y) ? (X) : (Y))

(This is not the best way to define a "minimum" macro in GNU C. See section
Duplication of Side Effects, for more information.)

To use a macro that expects arguments, you write the name of the macro followed by a
list of actual arguments in parentheses, separated by commas. The number of actual
arguments you give must match the number of arguments the macro expects. Examples
of use of the macro `min' include `min (1, 2)' and `min (x + 28, *p)'.

The expansion text of the macro depends on the arguments you use. Each of the argument
names of the macro is replaced, throughout the macro definition, with the corresponding
actual argument. Using the same macro `min' defined above, `min (1, 2)' expands into

((1) < (2) ? (1) : (2))

where `1' has been substituted for `X' and `2' for `Y'.

Likewise, `min (x + 28, *p)' expands into

((x + 28) < (*p) ? (x + 28) : (*p))

Parentheses in the actual arguments must balance; a comma within parentheses does not
end an argument. However, there is no requirement for brackets or braces to balance, and
they do not prevent a comma from separating arguments. Thus,

macro (array[x = y, x + 1])

Department of Computer Science (MCA), Christ University 52


Macro Processor for C/C++
passes two arguments to macro: `array[x = y' and `x + 1]'. If you want to supply `array[x
= y, x + 1]' as an argument, you must write it as `array[(x = y, x + 1)]', which is
equivalent C code.

After the actual arguments are substituted into the macro body, the entire result is
appended to the front of the remaining input, and the check for macro calls continues.
Therefore, the actual arguments can contain calls to other macros, either with or without
arguments, or even to the same macro. The macro body can also contain calls to other
macros. For example, `min (min (a, b), c)' expands into this text:

((((a) < (b) ? (a) : (b))) < (c)


? (((a) < (b) ? (a) : (b)))
: (c))

(Line breaks shown here for clarity would not actually be generated.)

If a macro foo takes one argument, and you want to supply an empty argument, you must
write at least some whitespace between the parentheses, like this: `foo ( )'. Just `foo ()' is
providing no arguments, which is an error if foo expects an argument. But `foo0 ()' is the
correct way to call a macro defined to take zero arguments, like this:

#define foo0() ...

If you use the macro name followed by something other than an open-parenthesis (after
ignoring any spaces, tabs and comments that follow), it is not a call to the macro, and the
preprocessor does not change what you have written. Therefore, it is possible for the
same name to be a variable or function in your program as well as a macro, and you can
choose in each instance whether to refer to the macro (if an actual argument list follows)
or the variable or function (if an argument list does not follow).

Department of Computer Science (MCA), Christ University 53


Macro Processor for C/C++
Such dual use of one name could be confusing and should be avoided except when the
two meanings are effectively synonymous: that is, when the name is both a macro and a
function and the two have similar effects. You can think of the name simply as a
function; use of the name for purposes other than calling it (such as, to take the address)
will refer to the function, while calls will expand the macro and generate better but
equivalent code. For example, you can use a function named `min' in the same source file
that defines the macro. If you write `&min' with no argument list, you refer to the
function. If you write `min (x, bb)', with an argument list, the macro is expanded. If you
write `(min) (a, bb)', where the name `min' is not followed by an open-parenthesis, the
macro is not expanded, so you wind up with a call to the function `min'.

You may not define the same name as both a simple macro and a macro with arguments.

In the definition of a macro with arguments, the list of argument names must follow the
macro name immediately with no space in between. If there is a space after the macro
name, the macro is defined as taking no arguments, and all the rest of the line is taken to
be the expansion. The reason for this is that it is often useful to define a macro that takes
no arguments and whose definition begins with an identifier in parentheses. This rule
about spaces makes it possible for you to do either this:

#define FOO(x) - 1 / (x)

(which defines `FOO' to take an argument and expand into minus the reciprocal of that
argument) or this:

#define BAR (x) - 1 / (x)

(which defines `BAR' to take no argument and always expand into `(x) - 1 / (x)').

Note that the uses of a macro with arguments can have spaces before the left parenthesis;
it's the definition where it matters whether there is a space.

Department of Computer Science (MCA), Christ University 54


Macro Processor for C/C++
Stringification

Stringification means turning a code fragment into a string constant whose contents are
the text for the code fragment. For example, stringifying `foo (z)' results in `"foo (z)"'.

In the C preprocessor, stringification is an option available when macro arguments are


substituted into the macro definition. In the body of the definition, when an argument
name appears, the character `#' before the name specifies stringification of the
corresponding actual argument when it is substituted at that point in the definition. The
same argument may be substituted in other places in the definition without stringification
if the argument name appears in those places with no `#'.

Here is an example of a macro definition that uses stringification:

#define WARN_IF(EXP) \
do { if (EXP) \
fprintf (stderr, "Warning: " #EXP "\n"); } \
while (0)

Here the actual argument for `EXP' is substituted once as given, into the `if' statement,
and once as stringified, into the argument to `fprintf'. The `do' and `while (0)' are a kludge
to make it possible to write `WARN_IF (arg);', which the resemblance of `WARN_IF' to
a function would make C programmers want to do; see section Swallowing the
Semicolon).

The stringification feature is limited to transforming one macro argument into one string
constant: there is no way to combine the argument with other text and then stringify it all
together. But the example above shows how an equivalent result can be obtained in ANSI
Standard C using the feature that adjacent string constants are concatenated as one string
constant. The preprocessor stringifies the actual value of `EXP' into a separate string
constant, resulting in text like

Department of Computer Science (MCA), Christ University 55


Macro Processor for C/C++
do { if (x == 0) \
fprintf (stderr, "Warning: " "x == 0" "\n"); } \
while (0)

but the C compiler then sees three consecutive string constants and concatenates them
into one, producing effectively

do { if (x == 0) \
fprintf (stderr, "Warning: x == 0\n"); } \
while (0)

Stringification in C involves more than putting doublequote characters around the


fragment; it is necessary to put backslashes in front of all doublequote characters, and all
backslashes in string and character constants, in order to get a valid C string constant with
the proper contents. Thus, stringifying `p = "foo\n";' results in `"p = \"foo\\n\";"'.
However, backslashes that are not inside of string or character constants are not
duplicated: `\n' by itself stringifies to `"\n"'.

Whitespace (including comments) in the text being stringified is handled according to


precise rules. All leading and trailing whitespace is ignored. Any sequence of whitespace
in the middle of the text is converted to a single space in the stringified result.

Concatenation

Concatenation means joining two strings into one. In the context of macro expansion,
concatenation refers to joining two lexical units into one longer one. Specifically, an
actual argument to the macro can be concatenated with another actual argument or with
fixed text to produce a longer name. The longer name might be the name of a function,
variable or type, or a C keyword; it might even be the name of another macro, in which
case it will be expanded.

Department of Computer Science (MCA), Christ University 56


Macro Processor for C/C++
When you define a macro, you request concatenation with the special operator `##' in the
macro body. When the macro is called, after actual arguments are substituted, all `##'
operators are deleted, and so is any whitespace next to them (including whitespace that
was part of an actual argument). The result is to concatenate the syntactic tokens on either
side of the `##'.

Consider a C program that interprets named commands. There probably needs to be a


table of commands, perhaps an array of structures declared as follows:

struct command
{
char *name;
void (*function) ();
};

struct command commands[] =


{
{ "quit", quit_command},
{ "help", help_command},
...
};

It would be cleaner not to have to give each command name twice, once in the string
constant and once in the function name. A macro which takes the name of a command as
an argument can make this unnecessary. The string constant can be created with
stringification, and the function name by concatenating the argument with `_command'.
Here is how it is done:

#define COMMAND(NAME) { #NAME, NAME ## _command }

Department of Computer Science (MCA), Christ University 57


Macro Processor for C/C++
struct command commands[] =
{
COMMAND (quit),
COMMAND (help),
...
};

The usual case of concatenation is concatenating two names (or a name and a number)
into a longer name. But this isn't the only valid case. It is also possible to concatenate two
numbers (or a number and a name, such as `1.5' and `e3') into a number. Also, multi-
character operators such as `+=' can be formed by concatenation. In some cases it is even
possible to piece together a string constant. However, two pieces of text that don't
together form a valid lexical unit cannot be concatenated. For example, concatenation
with `x' on one side and `+' on the other is not meaningful because those two characters
can't fit together in any lexical unit of C. The ANSI standard says that such attempts at
concatenation are undefined, but in the GNU C preprocessor it is well defined: it puts the
`x' and `+' side by side with no particular special results.

Keep in mind that the C preprocessor converts comments to whitespace before macros
are even considered. Therefore, you cannot create a comment by concatenating `/' and `*':
the `/*' sequence that starts a comment is not a lexical unit, but rather the beginning of a
"long" space character. Also, you can freely use comments next to a `##' in a macro
definition, or in actual arguments that will be concatenated, because the comments will
be converted to spaces at first sight, and concatenation will later discard the spaces.

Predefined Macros

Several simple macros are predefined. You can use them without giving definitions for
them. They fall into two classes: standard macros and system-specific macros.

Department of Computer Science (MCA), Christ University 58


Macro Processor for C/C++
Standard Predefined Macros

The standard predefined macros are available with the same meanings regardless of the
machine or operating system on which you are using GNU C. Their names all start and
end with double underscores. Those preceding __GNUC__ in this table are standardized
by ANSI C; the rest are GNU C extensions.

__FILE__
This macro expands to the name of the current input file, in the form of a C string
constant. The precise name returned is the one that was specified in `#include' or
as the input file name argument.
__LINE__
This macro expands to the current input line number, in the form of a decimal
integer constant. While we call it a predefined macro, it's a pretty strange macro,
since its "definition" changes with each new line of source code.

This and `__FILE__' are useful in generating an error message to report an


inconsistency detected by the program; the message can state the source line at
which the inconsistency was detected. For example,

fprintf (stderr, "Internal error: "


"negative string length "
"%d at %s, line %d.",
length, __FILE__, __LINE__);

A `#include' command changes the expansions of `__FILE__' and `__LINE__' to


correspond to the included file. At the end of that file, when processing resumes
on the input file that contained the `#include' command, the expansions of
`__FILE__' and `__LINE__' revert to the values they had before the `#include'
(but `__LINE__' is then incremented by one as processing moves to the line after
the `#include').
Department of Computer Science (MCA), Christ University 59
Macro Processor for C/C++
The expansions of both `__FILE__' and `__LINE__' are altered if a `#line'
command is used. See section Combining Source Files.

__INCLUDE_LEVEL__
This macro expands to a decimal integer constant that represents the depth of
nesting in include files. The value of this macro is incremented on every `#include'
command and decremented at every end of file.
__DATE__
This macro expands to a string constant that describes the date on which the
preprocessor is being run. The string constant contains eleven characters and looks
like `"Jan 29 1987"' or `"Apr 1 1905"'.
__TIME__
This macro expands to a string constant that describes the time at which the
preprocessor is being run. The string constant contains eight characters and looks
like `"23:59:01"'.
__STDC__
This macro expands to the constant 1, to signify that this is ANSI Standard C.
(Whether that is actually true depends on what C compiler will operate on the
output from the preprocessor.)
__GNUC__
This macro is defined if and only if this is GNU C. This macro is defined only
when the entire GNU C compiler is in use; if you invoke the preprocessor directly,
`__GNUC__' is undefined.
__GNUG__
The GNU C compiler defines this when the compilation language is C++; use
`__GNUG__' to distinguish between GNU C and GNU C++.
__cplusplus
The draft ANSI standard for C++ used to require predefining this variable. Though
it is no longer required, GNU C++ continues to define it, as do other popular C++

Department of Computer Science (MCA), Christ University 60


Macro Processor for C/C++
compilers. You can use `__cplusplus' to test whether a header is compiled by a C
compiler or a C++ compiler.
__STRICT_ANSI__
This macro is defined if and only if the `-ansi' switch was specified when GNU C
was invoked. Its definition is the null string. This macro exists primarily to direct
certain GNU header files not to define certain traditional Unix constructs which
are incompatible with ANSI C.
__BASE_FILE__
This macro expands to the name of the main input file, in the form of a C string
constant. This is the source file that was specified as an argument when the C
compiler was invoked.
__VERSION__
This macro expands to a string which describes the version number of GNU C.
The string is normally a sequence of decimal numbers separated by periods, such
as `"1.18"'. The only reasonable use of this macro is to incorporate it into a string
constant.
__OPTIMIZE__
This macro is defined in optimizing compilations. It causes certain GNU header
files to define alternative macro definitions for some system library functions. It is
unwise to refer to or test the definition of this macro unless you make very sure
that programs will execute with the same effect regardless.
__CHAR_UNSIGNED__
This macro is defined if and only if the data type char is unsigned on the target
machine. It exists to cause the standard header file `limit.h' to work correctly. It is
bad practice to refer to this macro yourself; instead, refer to the standard macros
defined in `limit.h'. The preprocessor uses this macro to determine whether or not
to sign-extend large character constants written in octal; see section The `#if'
Command.

Department of Computer Science (MCA), Christ University 61


Macro Processor for C/C++

Appendix B (C#)

C# (pronounced “See Sharp”) is a simple, modern, object-oriented, and type-safe


programming language. C# has its roots in the C family of languages and will be
immediately familiar to C, C++, and Java programmers. C# is standardized by ECMA
International as the ECMA-334 standard and by ISO/IEC as the ISO/IEC 23270
standard. Microsoft’s C# compiler for the .NET Framework is a conforming
implementation of both of these standards.

C# is an object-oriented language, but C# further includes support for component-


oriented programming. Contemporary software design increasingly relies on software
components in the form of self-contained and self-describing packages of functionality.
Key to such components is that they present a programming model with properties,
methods, and events; they have attributes that provide declarative information about the
component; and they incorporate their own documentation. C# provides language
constructs to directly support these concepts, making C# a very natural language in which
to create and use software components.

Several C# features aid in the construction of robust and durable applications: Garbage
collection automatically reclaims memory occupied by unused objects; exception
handling provides a structured and extensible approach to error detection and recovery;
and the type-safe design of the language makes it impossible to read from uninitialized
variables, to index arrays beyond their bounds, or to perform unchecked type casts.
C# has a unified type system. All C# types, including primitive types such as int and
double, inherit from a single root object type. Thus, all types share a set of common
operations, and values of any type can be stored, transported, and operated upon in a
consistent manner. Furthermore, C# supports both user-defined reference types and value

Department of Computer Science (MCA), Christ University 62


Macro Processor for C/C++
types, allowing dynamic allocation of objects as well as in-line storage of lightweight
structures.

To ensure that C# programs and libraries can evolve over time in a compatible manner,
much emphasis has been placed on versioning in C#’s design. Many programming
languages pay little attention to this issue, and, as a result, programs written in those
languages break more often than necessary when newer versions of dependent libraries
are introduced. Aspects of C#’s design that were directly influenced by versioning
considerations include the separate virtual and override modifiers, the rules for method
overload resolution, and support for explicit interface member declarations.

The greatest power of C# is the availability of various collections. Collections like Data
Tables , HashTables, ArrayLists are used in this project and these collections helped us
to do coding in efficient way.

The various collections in C# are as follows:

Array List:

The main problem of traditional arrays is that their size is fixed by the number you
specify when declaring the array variable: you cannot add items beyond the specified
dimension. Another limitation is that you cannot insert an item inside the list. To
overcome this, you can create a linked list. Instead of working from scratch, the .NET
Framework provides the ArrayList class. With the ArrayList class, you can add new
items to a list, insert items inside a list, arrange items of a list, check the existence of an
item in a list, remove an item from the list, inquire about the list, or destroy the list. These
operations are possible through various properties and methods.

Department of Computer Science (MCA), Christ University 63


Macro Processor for C/C++

HashTables:

Collections are used to store generic data types. Some of the collection classes available
in .NET Framework includes ArrayList, HashTable, Stack, and Queue. The Hashtable
object contains items in key/value pairs. The keys are used as indexes. We can search
value by using their corresponding key. Items are added to the Hashtable with the Add()
method. The data type of Hashtable is object and the default size of a Hashtable is 16.

Data Tables:

The DataTable has not received proper attentions in manybooks and articles. Often, the
authors get involved in explaining thedetails of a more versatile and novel object named
DataSet, thereby theDataTable object gets short-changed. The DataTable objects are
thefoundations of DataSets, and we will not be able to develop advanceddatabase
applications without understanding the principles of aDataTable.

A DataTable is an innovative addition to theDot Net Framework. Often a new developer


may confuse it with a databasetable. Typically, one or more DataTables are used in a
DataSet toconstruct a detached mini-database in the client's cache. However, aDataTable
may stand alone by its own right, and we may use it in manysituations that do not
necessarily warrant database connectivity orDataSets.

A DataTable is a relational database-liketable in the memory. It has a structural definition


(like databasetable definition), and constraints like Unique constraints. We may
alsodevelop database-like views. We may create hierarchical relationshipsamong many
DataTables dynamically in a DataSet.

Department of Computer Science (MCA), Christ University 64


Macro Processor for C/C++

Bibliography

Books
[B1] Beck Leland, An Introduction to System Programming, TMH 2006
[B2] Donovan, John, System programming, Pentice Hall Publications 2004
[B3] Dhamdhere D M, Systems programming and operating systems, TMH 2007

Websites
[W1] www.howstuffworks.com/analyser.html
[W2] www.codeguru.com/macro/mp2.html
[W3] www.programmersheaven.com/multimacro.htm

Department of Computer Science (MCA), Christ University 65

Das könnte Ihnen auch gefallen