source: src/Parser/ParseNode.h@ a17e7b8

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since a17e7b8 was 8e9cbb2, checked in by Peter A. Buhr <pabuhr@…>, 9 years ago

add more code to handle gcc extension and test program, second attempt

  • Property mode set to 100644
File size: 20.7 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ParseNode.h --
8//
9// Author : Rodolfo G. Esteves
10// Created On : Sat May 16 13:28:16 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Mon Jul 4 15:35:09 2016
13// Update Count : 260
14//
15
16#ifndef PARSENODE_H
17#define PARSENODE_H
18
19#include <string>
20#include <list>
21#include <iterator>
22#include <memory>
23
24#include "Common/utility.h"
25#include "Parser/LinkageSpec.h"
26#include "SynTree/Type.h"
27#include "SynTree/Expression.h"
28//#include "SynTree/Declaration.h"
29#include "Common/UniqueName.h"
30#include "SynTree/Label.h"
31
32class ExpressionNode;
33class CompositeExprNode;
34class CommaExprNode;
35class StatementNode;
36class CompoundStmtNode;
37class DeclarationNode;
38class InitializerNode;
39
40// Builder
41class ParseNode {
42 public:
43 ParseNode();
44 ParseNode( const std::string * );
45 ParseNode( const std::string & ); // for copy constructing subclasses
46 virtual ~ParseNode();
47
48 ParseNode *get_link() const { return next; }
49 ParseNode *get_last();
50 ParseNode *set_link( ParseNode * );
51 void set_next( ParseNode *newlink ) { next = newlink; }
52
53 virtual ParseNode *clone() const { return 0; };
54
55 const std::string &get_name() const { return name; }
56 void set_name( const std::string &newValue ) { name = newValue; }
57
58 virtual void print( std::ostream &, int indent = 0 ) const;
59 virtual void printList( std::ostream &, int indent = 0 ) const;
60
61 ParseNode &operator,( ParseNode &);
62 protected:
63 std::string name;
64 static int indent_by;
65 ParseNode *next;
66};
67
68ParseNode *mkList( ParseNode & );
69
70class ExpressionNode : public ParseNode {
71 public:
72 ExpressionNode();
73 ExpressionNode( const std::string * );
74 ExpressionNode( const ExpressionNode &other );
75 virtual ~ExpressionNode() { delete argName; } // cannot delete argName because it might be referenced elsewhere
76
77 virtual ExpressionNode *clone() const = 0;
78
79 virtual CommaExprNode *add_to_list( ExpressionNode * );
80
81 ExpressionNode *get_argName() const { return argName; }
82 ExpressionNode *set_argName( const std::string *aName );
83 ExpressionNode *set_argName( ExpressionNode *aDesignator );
84 bool get_extension() const { return extension; }
85 ExpressionNode *set_extension( bool exten ) { extension = exten; return this; }
86
87 virtual void print( std::ostream &, int indent = 0) const = 0;
88 virtual void printOneLine( std::ostream &, int indent = 0) const = 0;
89
90 virtual Expression *build() const = 0;
91 protected:
92 void printDesignation ( std::ostream &, int indent = 0) const;
93 private:
94 ExpressionNode *argName = 0;
95 bool extension = false;
96};
97
98template< typename T >
99struct maybeBuild_t<Expression, T> {
100 static inline Expression * doit( const T *orig ) {
101 if ( orig ) {
102 Expression *p = orig->build();
103 p->set_extension( orig->get_extension() );
104 return p;
105 } else {
106 return 0;
107 } // if
108 }
109};
110
111// NullExprNode is used in tuples as a place-holder where a tuple component is omitted e.g., [ 2, , 3 ]
112class NullExprNode : public ExpressionNode {
113 public:
114 NullExprNode();
115
116 virtual NullExprNode *clone() const;
117
118 virtual void print( std::ostream &, int indent = 0) const;
119 virtual void printOneLine( std::ostream &, int indent = 0) const;
120
121 virtual Expression *build() const;
122};
123
124class ConstantNode : public ExpressionNode {
125 public:
126 enum Type { Integer, Float, Character, String };
127
128 ConstantNode( ConstantExpr * );
129 ConstantNode( const ConstantNode &other ) : expr( other.expr->clone() ) {};
130 ~ConstantNode() { delete expr; }
131
132 virtual ConstantNode *clone() const { return new ConstantNode( *this ); }
133 virtual void print( std::ostream &, int indent = 0) const;
134 virtual void printOneLine( std::ostream &, int indent = 0) const;
135
136 ConstantNode *appendstr( const std::string *newValue );
137
138 Expression *build() const;
139 private:
140 ConstantExpr *expr;
141};
142
143ConstantNode *makeConstant( ConstantNode::Type, std::string * );
144ConstantNode *makeConstantStr( ConstantNode::Type type, std::string *str );
145
146class VarRefNode : public ExpressionNode {
147 public:
148 VarRefNode();
149 VarRefNode( const std::string *, bool isLabel = false );
150 VarRefNode( const VarRefNode &other );
151
152 virtual Expression *build() const ;
153
154 virtual VarRefNode *clone() const { return new VarRefNode( *this ); }
155
156 virtual void print( std::ostream &, int indent = 0 ) const;
157 virtual void printOneLine( std::ostream &, int indent = 0 ) const;
158 private:
159 bool isLabel;
160};
161
162class DesignatorNode : public ExpressionNode {
163 public:
164 DesignatorNode( ExpressionNode *expr, bool isArrayIndex = false );
165 DesignatorNode( const DesignatorNode &other );
166
167 virtual Expression *build() const ;
168 virtual DesignatorNode *clone() const { return new DesignatorNode( *this ); }
169
170 virtual void print( std::ostream &, int indent = 0 ) const;
171 virtual void printOneLine( std::ostream &, int indent = 0 ) const;
172 private:
173 bool isArrayIndex;
174};
175
176class TypeValueNode : public ExpressionNode {
177 public:
178 TypeValueNode( DeclarationNode * );
179 TypeValueNode( const TypeValueNode &other );
180
181 DeclarationNode *get_decl() const { return decl; }
182
183 virtual Expression *build() const ;
184
185 virtual TypeValueNode *clone() const { return new TypeValueNode( *this ); }
186
187 virtual void print( std::ostream &, int indent = 0) const;
188 virtual void printOneLine( std::ostream &, int indent = 0) const;
189 private:
190 DeclarationNode *decl;
191};
192
193class OperatorNode : public ExpressionNode {
194 public:
195 enum Type { TupleC, Comma, TupleFieldSel, // n-adic
196 // triadic
197 Cond, NCond,
198 // diadic
199 SizeOf, AlignOf, OffsetOf, Attr, Plus, Minus, Mul, Div, Mod, Or, And,
200 BitOr, BitAnd, Xor, Cast, LShift, RShift, LThan, GThan, LEThan, GEThan, Eq, Neq,
201 Assign, MulAssn, DivAssn, ModAssn, PlusAssn, MinusAssn, LSAssn, RSAssn, AndAssn, ERAssn, OrAssn,
202 Index, FieldSel, PFieldSel, Range,
203 // monadic
204 UnPlus, UnMinus, AddressOf, PointTo, Neg, BitNeg, Incr, IncrPost, Decr, DecrPost, LabelAddress,
205 Ctor, Dtor,
206 };
207
208 OperatorNode( Type t );
209 OperatorNode( const OperatorNode &other );
210 virtual ~OperatorNode();
211
212 virtual OperatorNode *clone() const { return new OperatorNode( *this ); }
213
214 Type get_type() const;
215 const char *get_typename() const;
216
217 virtual void print( std::ostream &, int indent = 0) const;
218 virtual void printOneLine( std::ostream &, int indent = 0) const;
219
220 virtual Expression *build() const { return 0; }
221 private:
222 Type type;
223};
224
225class CompositeExprNode : public ExpressionNode {
226 public:
227 CompositeExprNode();
228 CompositeExprNode( const std::string * );
229 CompositeExprNode( ExpressionNode *f, ExpressionNode *args = 0 );
230 CompositeExprNode( ExpressionNode *f, ExpressionNode *arg1, ExpressionNode *arg2 );
231 CompositeExprNode( const CompositeExprNode &other );
232 virtual ~CompositeExprNode();
233
234 virtual CompositeExprNode *clone() const { return new CompositeExprNode( *this ); }
235 virtual Expression *build() const;
236
237 virtual void print( std::ostream &, int indent = 0) const;
238 virtual void printOneLine( std::ostream &, int indent = 0) const;
239
240 void set_function( ExpressionNode * );
241 void set_args( ExpressionNode * );
242
243 void add_arg( ExpressionNode * );
244
245 ExpressionNode *get_function() const;
246 ExpressionNode *get_args() const;
247 private:
248 ExpressionNode *function;
249 ExpressionNode *arguments;
250};
251
252class AsmExprNode : public ExpressionNode {
253 public:
254 AsmExprNode();
255 AsmExprNode( ExpressionNode *inout, ConstantNode *constraint, ExpressionNode *operand ) : inout( inout ), constraint( constraint ), operand( operand ) {}
256 virtual ~AsmExprNode() { delete inout; delete constraint; delete operand; }
257
258 virtual AsmExprNode *clone() const { return new AsmExprNode( *this ); }
259 virtual Expression *build() const;
260
261 virtual void print( std::ostream &, int indent = 0) const;
262 virtual void printOneLine( std::ostream &, int indent = 0) const;
263
264 ExpressionNode *get_inout() const { return inout; };
265 void set_inout( ExpressionNode *newValue ) { inout = newValue; }
266
267 ConstantNode *get_constraint() const { return constraint; };
268 void set_constraint( ConstantNode *newValue ) { constraint = newValue; }
269
270 ExpressionNode *get_operand() const { return operand; };
271 void set_operand( ExpressionNode *newValue ) { operand = newValue; }
272 private:
273 ExpressionNode *inout;
274 ConstantNode *constraint;
275 ExpressionNode *operand;
276};
277
278class LabelNode : public ExpressionNode {
279 public:
280 virtual Expression *build() const { return NULL; }
281 virtual LabelNode *clone() const { return new LabelNode( *this ); }
282
283 virtual void print( std::ostream &, int indent = 0) const;
284 virtual void printOneLine( std::ostream &, int indent = 0) const;
285
286 const std::list< Label > &get_labels() const { return labels; };
287 void append_label( std::string *label ) { labels.push_back( *label ); delete label; }
288 private:
289 std::list< Label > labels;
290};
291
292class CommaExprNode : public CompositeExprNode {
293 public:
294 CommaExprNode();
295 CommaExprNode( ExpressionNode * );
296 CommaExprNode( ExpressionNode *, ExpressionNode * );
297 CommaExprNode( const CommaExprNode &other );
298
299 virtual CommaExprNode *add_to_list( ExpressionNode * );
300 virtual CommaExprNode *clone() const { return new CommaExprNode( *this ); }
301};
302
303class ForCtlExprNode : public ExpressionNode {
304 public:
305 ForCtlExprNode( ParseNode *, ExpressionNode *, ExpressionNode * ) throw ( SemanticError );
306 ForCtlExprNode( const ForCtlExprNode &other );
307 ~ForCtlExprNode();
308
309 StatementNode *get_init() const { return init; }
310 ExpressionNode *get_condition() const { return condition; }
311 ExpressionNode *get_change() const { return change; }
312
313 virtual ForCtlExprNode *clone() const { return new ForCtlExprNode( *this ); }
314 virtual Expression *build() const;
315
316 virtual void print( std::ostream &, int indent = 0 ) const;
317 virtual void printOneLine( std::ostream &, int indent = 0 ) const;
318 private:
319 StatementNode *init;
320 ExpressionNode *condition;
321 ExpressionNode *change;
322};
323
324class ValofExprNode : public ExpressionNode {
325 public:
326 ValofExprNode();
327 ValofExprNode( StatementNode *s = 0 );
328 ValofExprNode( const ValofExprNode &other );
329 ~ValofExprNode();
330
331 virtual ValofExprNode *clone() const { return new ValofExprNode( *this ); }
332
333 StatementNode *get_body() const { return body; }
334 void print( std::ostream &, int indent = 0 ) const;
335 void printOneLine( std::ostream &, int indent = 0 ) const;
336 Expression *build() const;
337
338 private:
339 StatementNode *body;
340};
341
342class TypeData;
343
344class DeclarationNode : public ParseNode {
345 public:
346 enum Qualifier { Const, Restrict, Volatile, Lvalue, Atomic };
347 enum StorageClass { Extern, Static, Auto, Register, Inline, Fortran, Noreturn, Threadlocal, NoStorageClass, };
348 enum BasicType { Char, Int, Float, Double, Void, Bool, Complex, Imaginary };
349 enum Modifier { Signed, Unsigned, Short, Long };
350 enum Aggregate { Struct, Union, Trait };
351 enum TypeClass { Type, Dtype, Ftype };
352 enum BuiltinType { Valist };
353
354 static const char *storageName[];
355 static const char *qualifierName[];
356 static const char *basicTypeName[];
357 static const char *modifierName[];
358 static const char *aggregateName[];
359 static const char *typeClassName[];
360 static const char *builtinTypeName[];
361
362 static DeclarationNode *newFunction( std::string *name, DeclarationNode *ret, DeclarationNode *param, StatementNode *body, bool newStyle = false );
363 static DeclarationNode *newQualifier( Qualifier );
364 static DeclarationNode *newStorageClass( StorageClass );
365 static DeclarationNode *newBasicType( BasicType );
366 static DeclarationNode *newModifier( Modifier );
367 static DeclarationNode *newForall( DeclarationNode *);
368 static DeclarationNode *newFromTypedef( std::string *);
369 static DeclarationNode *newAggregate( Aggregate kind, const std::string *name, ExpressionNode *actuals, DeclarationNode *fields );
370 static DeclarationNode *newEnum( std::string *name, DeclarationNode *constants );
371 static DeclarationNode *newEnumConstant( std::string *name, ExpressionNode *constant );
372 static DeclarationNode *newName( std::string *);
373 static DeclarationNode *newFromTypeGen( std::string *, ExpressionNode *params );
374 static DeclarationNode *newTypeParam( TypeClass, std::string *);
375 static DeclarationNode *newTrait( std::string *name, DeclarationNode *params, DeclarationNode *asserts );
376 static DeclarationNode *newTraitUse( std::string *name, ExpressionNode *params );
377 static DeclarationNode *newTypeDecl( std::string *name, DeclarationNode *typeParams );
378 static DeclarationNode *newPointer( DeclarationNode *qualifiers );
379 static DeclarationNode *newArray( ExpressionNode *size, DeclarationNode *qualifiers, bool isStatic );
380 static DeclarationNode *newVarArray( DeclarationNode *qualifiers );
381 static DeclarationNode *newBitfield( ExpressionNode *size );
382 static DeclarationNode *newTuple( DeclarationNode *members );
383 static DeclarationNode *newTypeof( ExpressionNode *expr );
384 static DeclarationNode *newAttr( std::string *, ExpressionNode *expr );
385 static DeclarationNode *newAttr( std::string *, DeclarationNode *type );
386 static DeclarationNode *newBuiltinType( BuiltinType );
387
388 DeclarationNode *addQualifiers( DeclarationNode *);
389 DeclarationNode *copyStorageClasses( DeclarationNode *);
390 DeclarationNode *addType( DeclarationNode *);
391 DeclarationNode *addTypedef();
392 DeclarationNode *addAssertions( DeclarationNode *);
393 DeclarationNode *addName( std::string *);
394 DeclarationNode *addBitfield( ExpressionNode *size );
395 DeclarationNode *addVarArgs();
396 DeclarationNode *addFunctionBody( StatementNode *body );
397 DeclarationNode *addOldDeclList( DeclarationNode *list );
398 DeclarationNode *addPointer( DeclarationNode *qualifiers );
399 DeclarationNode *addArray( DeclarationNode *array );
400 DeclarationNode *addNewPointer( DeclarationNode *pointer );
401 DeclarationNode *addNewArray( DeclarationNode *array );
402 DeclarationNode *addParamList( DeclarationNode *list );
403 DeclarationNode *addIdList( DeclarationNode *list ); // old-style functions
404 DeclarationNode *addInitializer( InitializerNode *init );
405
406 DeclarationNode *cloneType( std::string *newName );
407 DeclarationNode *cloneType( DeclarationNode *existing );
408 DeclarationNode *cloneType( int ) { return cloneType( ( std::string *)0 ); }
409 DeclarationNode *cloneBaseType( std::string *newName );
410 DeclarationNode *cloneBaseType( DeclarationNode *newdecl );
411
412 DeclarationNode *appendList( DeclarationNode * );
413
414 DeclarationNode *clone() const;
415 void print( std::ostream &, int indent = 0 ) const;
416 void printList( std::ostream &, int indent = 0 ) const;
417
418 Declaration *build() const;
419 ::Type *buildType() const;
420
421 bool get_hasEllipsis() const;
422 const std::string &get_name() const { return name; }
423 LinkageSpec::Type get_linkage() const { return linkage; }
424 DeclarationNode *extractAggregate() const;
425 ExpressionNode *get_enumeratorValue() const { return enumeratorValue; }
426
427 bool get_extension() const { return extension; }
428 DeclarationNode *set_extension( bool exten ) { extension = exten; return this; }
429
430 DeclarationNode();
431 ~DeclarationNode();
432 private:
433 StorageClass buildStorageClass() const;
434 bool buildFuncSpecifier( StorageClass key ) const;
435
436 TypeData *type;
437 std::string name;
438 std::list< StorageClass > storageClasses;
439 std::list< std::string > attributes;
440 ExpressionNode *bitfieldWidth;
441 ExpressionNode *enumeratorValue;
442 InitializerNode *initializer;
443 bool hasEllipsis;
444 LinkageSpec::Type linkage;
445 bool extension = false;
446
447 static UniqueName anonymous;
448}; // DeclarationNode
449
450class StatementNode : public ParseNode {
451 public:
452 enum Type { Exp, If, Switch, Case, Default, Choose, Fallthru,
453 While, Do, For,
454 Goto, Continue, Break, Return, Throw,
455 Try, Catch, Finally, Asm,
456 Decl
457 };
458
459 StatementNode();
460 StatementNode( const std::string *name );
461 StatementNode( Type t, ExpressionNode *control = 0, StatementNode *block = 0 );
462 StatementNode( Type t, std::string *target );
463 StatementNode( DeclarationNode *decl );
464
465 ~StatementNode();
466
467 static StatementNode *newCatchStmt( DeclarationNode *d = 0, StatementNode *s = 0, bool catchRestP = false );
468
469 StatementNode *set_block( StatementNode *b ) { block = b; return this; }
470 StatementNode *get_block() const { return block; }
471
472 void set_control( ExpressionNode *c ) { control = c; }
473 ExpressionNode *get_control() const { return control; }
474
475 StatementNode::Type get_type() const { return type; }
476
477 StatementNode *add_label( const std::string * );
478 const std::list<std::string> &get_labels() const { return labels; }
479
480 void addDeclaration( DeclarationNode *newDecl ) { decl = newDecl; }
481 void setCatchRest( bool newVal ) { isCatchRest = newVal; }
482
483 std::string get_target() const;
484
485 StatementNode *add_controlexp( ExpressionNode * );
486 StatementNode *append_block( StatementNode * );
487 StatementNode *append_last_case( StatementNode * );
488
489 void print( std::ostream &, int indent = 0) const;
490 virtual StatementNode *clone() const;
491 virtual Statement *build() const;
492 private:
493 static const char *StType[];
494 Type type;
495 ExpressionNode *control;
496 StatementNode *block;
497 std::list<std::string> labels;
498 std::string *target; // target label for jump statements
499 DeclarationNode *decl;
500 bool isCatchRest;
501}; // StatementNode
502
503class CompoundStmtNode : public StatementNode {
504 public:
505 CompoundStmtNode();
506 CompoundStmtNode( const std::string * );
507 CompoundStmtNode( StatementNode * );
508 ~CompoundStmtNode();
509
510 void add_statement( StatementNode * );
511
512 void print( std::ostream &, int indent = 0 ) const;
513 virtual Statement *build() const;
514 private:
515 StatementNode *first, *last;
516};
517
518class AsmStmtNode : public StatementNode {
519 public:
520 AsmStmtNode( Type, bool voltile, ConstantNode *instruction, ExpressionNode *output = 0, ExpressionNode *input = 0, ConstantNode *clobber = 0, LabelNode *gotolabels = 0 );
521 ~AsmStmtNode();
522
523 void print( std::ostream &, int indent = 0 ) const;
524 Statement *build() const;
525 private:
526 bool voltile;
527 ConstantNode *instruction;
528 ExpressionNode *output, *input;
529 ConstantNode *clobber;
530 std::list< Label > gotolabels;
531};
532
533class NullStmtNode : public CompoundStmtNode {
534 public:
535 Statement *build() const;
536 void print( std::ostream &, int indent = 0 ) const;
537};
538
539class InitializerNode : public ParseNode {
540 public:
541 InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode *des = 0 );
542 InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode *des = 0 );
543 ~InitializerNode();
544
545 ExpressionNode *get_expression() const { return expr; }
546
547 InitializerNode *set_designators( ExpressionNode *des ) { designator = des; return this; }
548 ExpressionNode *get_designators() const { return designator; }
549
550 InitializerNode *set_maybeConstructed( bool value ) { maybeConstructed = value; return this; }
551 bool get_maybeConstructed() const { return maybeConstructed; }
552
553 InitializerNode *next_init() const { return kids; }
554
555 void print( std::ostream &, int indent = 0 ) const;
556 void printOneLine( std::ostream & ) const;
557
558 virtual Initializer *build() const;
559 private:
560 ExpressionNode *expr;
561 bool aggregate;
562 ExpressionNode *designator; // may be list
563 InitializerNode *kids;
564 bool maybeConstructed;
565};
566
567class CompoundLiteralNode : public ExpressionNode {
568 public:
569 CompoundLiteralNode( DeclarationNode *type, InitializerNode *kids );
570 CompoundLiteralNode( const CompoundLiteralNode &type );
571 ~CompoundLiteralNode();
572
573 virtual CompoundLiteralNode *clone() const;
574
575 DeclarationNode *get_type() const { return type; }
576 CompoundLiteralNode *set_type( DeclarationNode *t ) { type = t; return this; }
577
578 InitializerNode *get_initializer() const { return kids; }
579 CompoundLiteralNode *set_initializer( InitializerNode *k ) { kids = k; return this; }
580
581 void print( std::ostream &, int indent = 0 ) const;
582 void printOneLine( std::ostream &, int indent = 0 ) const;
583
584 virtual Expression *build() const;
585 private:
586 DeclarationNode *type;
587 InitializerNode *kids;
588};
589
590template< typename SynTreeType, typename NodeType >
591void buildList( const NodeType *firstNode, std::list< SynTreeType *> &outputList ) {
592 SemanticError errors;
593 std::back_insert_iterator< std::list< SynTreeType *> > out( outputList );
594 const NodeType *cur = firstNode;
595
596 while ( cur ) {
597 try {
598// SynTreeType *result = dynamic_cast< SynTreeType *>( maybeBuild<typename std::result_of<decltype(&NodeType::build)(NodeType)>::type>( cur ) );
599 SynTreeType *result = dynamic_cast< SynTreeType *>( maybeBuild<typename std::pointer_traits<decltype(cur->build())>::element_type>( cur ) );
600 if ( result ) {
601 *out++ = result;
602 } else {
603 } // if
604 } catch( SemanticError &e ) {
605 errors.append( e );
606 } // try
607 cur = dynamic_cast< NodeType *>( cur->get_link() );
608 } // while
609 if ( ! errors.isEmpty() ) {
610 throw errors;
611 } // if
612}
613
614// in DeclarationNode.cc
615void buildList( const DeclarationNode *firstNode, std::list< Declaration * > &outputList );
616void buildList( const DeclarationNode *firstNode, std::list< DeclarationWithType *> &outputList );
617void buildTypeList( const DeclarationNode *firstNode, std::list< Type * > &outputList );
618
619// in ExpressionNode.cc
620ExpressionNode *flattenCommas( ExpressionNode *list );
621ExpressionNode *tupleContents( ExpressionNode *tuple );
622
623#endif // PARSENODE_H
624
625// Local Variables: //
626// tab-width: 4 //
627// mode: c++ //
628// compile-command: "make install" //
629// End: //
Note: See TracBrowser for help on using the repository browser.