source: src/Parser/ParseNode.h @ 0f8e4ac

aaron-thesisarm-ehcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 0f8e4ac was 0f8e4ac, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

change Label from a string typedef to a class

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