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 repositioning 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 Abstract 1. Introduction 1.1. Detailed Problem Definition 1.2. Block Diagram 2. Analysis 2.1. Domain Theory of the Problem 2.2. SS Concept used 2.3. Hardware and Software Requirements 2.4. Description of tools used System Design 3.1. Modular Design 3.2. Detail for each Module 3.3. Input Specifications 3.4. Output Specifications Implementation 4.1. Screen Shots 4.2. Sample Code Testing 5.1. Test Cases 5.2. Test Reports Conclusion 6.1. Advantages and Disadvantages 6.2. Future Enhancements

iii iv 2 4

6 7 9 9

3.

11 13 17 17

4.

22 26

5.

44 45

6.

48 49

References Appendix A (Macros) Appendix B (C# Programming) Bibliography

51 62 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 Macro definitions Extract macros with name and definition

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 Less use of functions for calling repeated code Less overhead when less functions are used Reduced processing time. (Although, code may be repeated, it is required and is not redundant. Therefore, the source code remains efficient) Programming tool that is vastly used Helps reduce spaghetti code and ultimately makes code more readable. Helps with the use of variables even in repeated code. Similar to parameters for functions, but without the overhead Replaces text in code as the user wished and contains no references nor pointers Usage of pre-processing tools that prepare source code for compilation Conditional compilation depending on certain system architecture and requirements 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 <macroname> 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: Macros can take parameters whose values can be replaced within the macro expansion. This makes macro usage more dynamic Macros can be used to conditionally include code depending on some condition. This is useful for codes which may vary on different architectures. 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
Pentium 60 MHz or higher 8 MB RAM or higher 10 MB hard-disk space free (not including swap space required for the OS)

Software Requirements
Borland Turbo C compiler or any other version compatible with IO streams Windows 98 or later 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 multiparadigm programming language encompassing imperative, functional, generic, objectoriented (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 prematurely 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 mnt_index Description Index to macro name

Mnt_name

Macro name

Mnt_type

Type of macroo-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 mdt_index Description 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 Arg_index Description 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 Effectively replaces code that was meant for replacement with the help of macros. Used concepts such as file pointers, structures to carry out its tasks 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. Produces the output file, even if there are errors or warnings in the input file. Maintains a separate input file and a separate output file for data verification and rectification. Maintains macro names and their definitions in structures, thereby reducing the amount of resources involved with character arrays and is useful for debugging purposes. 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 openparenthesis 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, multicharacter 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 componentoriented 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/multima

Sign up to vote on this title
UsefulNot useful

Master Your Semester with Scribd & The New York Times

Special offer: Get 4 months of Scribd and The New York Times for just $1.87 per week!

Master Your Semester with a Special Offer from Scribd & The New York Times