A CIL Tutorial - Department of Computer Science - ETH Zürich
A CIL Tutorial - Department of Computer Science - ETH Zürich A CIL Tutorial - Department of Computer Science - ETH Zürich
Chapter 14 Implementing a simple DSL When writing C code, one of the tasks that annoys me a lot is writing code to handle command line arguments. Thus, in this chapter we'll use CIL to put together a simple DSL for describing command line arguments. The module below will analyze a description of the arguments provided by the programmer, and generate code for parsing the command line, and checking the arguments for consistency. In particular, the goal is for the programmer to give a description like the one below at global scope: argument(int, intarg) { .short form = "i", .help text = "An integer argument (>0)", .format = "%d", .def = 1, .requires = arg assert(intarg > 0), .has opt = ARG HAS OPT, }; We can provide this syntax using CIL's attribute syntax along with judicious use of pre-processor macros. The macros, which are dened in ciltut-include/ciltut.h, declare variables for storing the command line arguments and their options, along with a structure type with elds for storing the properties of the argument. The code above is essentially an initializer list for those structure elds. The CIL code below will generate code to parse the command line arguments according to the options specied in the structure eld using the getopt long C Library call. 14.1 tut14.ml First, we'll declare types for representing requirements for the command line arguments along with some utility functions. Then, we'll write functions for extracting the requirements from the syntax mentioned above. Finally, we'll use CIL's interpreted constructors to generate the loop that calls 114
CHAPTER 14. IMPLEMENTING A SIMPLE DSL 115 getopt long and uses sscanf to parse any options the arguemnts might have. 14.1.1 Specication Extraction The argument type is where we'll collect the information the programmer gives us about the command line arguments. type argument = { mutable argName : string; (∗ The name of the argument, i.e. -- ∗) mutable argType : typ; (∗ The type of the argument ∗) mutable argShort : string; (∗ The short form of the argument, i.e. -n ∗) mutable argHelp : string; (∗ The help message for the argument ∗) mutable argFmt : string; (∗ The format specier for sscanf ∗) mutable argDef : exp; (∗ The default value of the argument ∗) mutable argReq : exp; (∗ An assertion about the argument ∗) mutable argOpt : bool; (∗ Whether the argument is optional ∗) mutable argVi : varinfo; (∗ The global varialbe for the argument ∗) mutable argGot : varinfo; (∗ Global variable indicating whether the argument was given ∗) mutable argOption : bool; (∗ Whether the argument as a parameter ∗) } The function makeArgument makes a fresh argument initialized with dummy values. let makeArgument () = (∗ ... ∗) Now that we've dened the argument type, we can write utility functions for extracting information from type attributes. In particular, structure types that should be interpreted as argument speci- cations are annotated with the ciltutarg type attribute. Also, we extract the parameter to the ciltut assert attribute on the type of the requires eld of the argument structure to be used as an assertion that must be true of the argument, e.g. intarg > 0 in the example above. As usual, we begin by dening some global variables for the string constants, along with a list of the strings. let argStr = "ciltutarg" let assertStr = "ciltut assert" let mandatoryStr = "mandatory" let attr strings = [argStr; assertStr; mandatoryStr; ] The functions hasArgAttr, hasAssertAttr, and hasMandatoryAttr return true if their arguments have the indicated attributes.
- Page 65 and 66: CHAPTER 8. DEPENDANT TYPE QUALIFIER
- Page 67 and 68: CHAPTER 8. DEPENDANT TYPE QUALIFIER
- Page 69 and 70: CHAPTER 8. DEPENDANT TYPE QUALIFIER
- Page 71 and 72: CHAPTER 8. DEPENDANT TYPE QUALIFIER
- Page 73 and 74: Chapter 9 Type Qualier Inference In
- Page 75 and 76: CHAPTER 9. TYPE QUALIFIER INFERENCE
- Page 77 and 78: CHAPTER 9. TYPE QUALIFIER INFERENCE
- Page 79 and 80: CHAPTER 9. TYPE QUALIFIER INFERENCE
- Page 81 and 82: CHAPTER 9. TYPE QUALIFIER INFERENCE
- Page 83 and 84: Chapter 10 Adding a New Kind of Sta
- Page 85 and 86: CHAPTER 10. ADDING A NEW KIND OF ST
- Page 87 and 88: CHAPTER 10. ADDING A NEW KIND OF ST
- Page 89 and 90: CHAPTER 10. ADDING A NEW KIND OF ST
- Page 91 and 92: CHAPTER 10. ADDING A NEW KIND OF ST
- Page 93 and 94: Chapter 11 Program Verication In th
- Page 95 and 96: CHAPTER 11. PROGRAM VERIFICATION 93
- Page 97 and 98: CHAPTER 11. PROGRAM VERIFICATION 95
- Page 99 and 100: CHAPTER 11. PROGRAM VERIFICATION 97
- Page 101 and 102: CHAPTER 11. PROGRAM VERIFICATION 99
- Page 103 and 104: CHAPTER 11. PROGRAM VERIFICATION 10
- Page 105 and 106: CHAPTER 11. PROGRAM VERIFICATION 10
- Page 107 and 108: Chapter 12 Comments CIL has a very
- Page 109 and 110: CHAPTER 12. COMMENTS 107 let printC
- Page 111 and 112: References [1] Lin Tan, Ding Yuan,
- Page 113 and 114: CHAPTER 13. WHOLE-PROGRAM ANALYSIS
- Page 115: CHAPTER 13. WHOLE-PROGRAM ANALYSIS
- Page 119 and 120: CHAPTER 14. IMPLEMENTING A SIMPLE D
- Page 121 and 122: CHAPTER 14. IMPLEMENTING A SIMPLE D
- Page 123 and 124: CHAPTER 14. IMPLEMENTING A SIMPLE D
- Page 125 and 126: CHAPTER 14. IMPLEMENTING A SIMPLE D
- Page 127 and 128: Chapter 15 Automated Test Generatio
- Page 129 and 130: CHAPTER 15. AUTOMATED TEST GENERATI
- Page 131 and 132: CHAPTER 15. AUTOMATED TEST GENERATI
- Page 133 and 134: CHAPTER 15. AUTOMATED TEST GENERATI
- Page 135 and 136: Index A (module), 10, 13, 15, 10, 1
- Page 137 and 138: INDEX 135 isCacheReportType, 11, 11
CHAPTER 14. IMPLEMENTING A SIMPLE DSL 115<br />
getopt long and uses sscanf to parse any options the arguemnts might have.<br />
14.1.1 Specication Extraction<br />
The argument type is where we'll collect the information the programmer gives us about the command<br />
line arguments.<br />
type argument = {<br />
mutable argName : string; (∗ The name <strong>of</strong> the argument, i.e. -- ∗)<br />
mutable argType : typ; (∗ The type <strong>of</strong> the argument ∗)<br />
mutable argShort : string; (∗ The short form <strong>of</strong> the argument, i.e. -n ∗)<br />
mutable argHelp : string; (∗ The help message for the argument ∗)<br />
mutable argFmt : string; (∗ The format specier for sscanf ∗)<br />
mutable argDef : exp; (∗ The default value <strong>of</strong> the argument ∗)<br />
mutable argReq : exp; (∗ An assertion about the argument ∗)<br />
mutable argOpt : bool; (∗ Whether the argument is optional ∗)<br />
mutable argVi : varinfo; (∗ The global varialbe for the argument ∗)<br />
mutable argGot : varinfo; (∗ Global variable indicating whether the argument was given ∗)<br />
mutable argOption : bool; (∗ Whether the argument as a parameter ∗)<br />
}<br />
The function makeArgument makes a fresh argument initialized with dummy values.<br />
let makeArgument () = (∗ ... ∗)<br />
Now that we've dened the argument type, we can write utility functions for extracting information<br />
from type attributes. In particular, structure types that should be interpreted as argument speci-<br />
cations are annotated with the ciltutarg type attribute. Also, we extract the parameter to the<br />
ciltut assert attribute on the type <strong>of</strong> the requires eld <strong>of</strong> the argument structure to be used as<br />
an assertion that must be true <strong>of</strong> the argument, e.g. intarg > 0 in the example above.<br />
As usual, we begin by dening some global variables for the string constants, along with a list<br />
<strong>of</strong> the strings.<br />
let argStr = "ciltutarg"<br />
let assertStr = "ciltut assert"<br />
let mandatoryStr = "mandatory"<br />
let attr strings = [argStr; assertStr; mandatoryStr; ]<br />
The functions hasArgAttr, hasAssertAttr, and hasMandatoryAttr return true if their arguments<br />
have the indicated attributes.