Changes in / [077810d:9d944b2]
- Files:
-
- 16 edited
-
doc/LaTeXmacros/common.tex (modified) (3 diffs)
-
doc/generic_types/generic_types.tex (modified) (9 diffs)
-
doc/rob_thesis/ctordtor.tex (modified) (1 diff)
-
doc/rob_thesis/tuples.tex (modified) (3 diffs)
-
src/CodeGen/CodeGenerator.cc (modified) (2 diffs)
-
src/InitTweak/FixInit.cc (modified) (2 diffs)
-
src/InitTweak/GenInit.cc (modified) (1 diff)
-
src/Parser/ExpressionNode.cc (modified) (2 diffs)
-
src/Parser/parser.yy (modified) (2 diffs)
-
src/SymTab/Indexer.cc (modified) (2 diffs)
-
src/SymTab/Validate.cc (modified) (3 diffs)
-
src/SynTree/Expression.cc (modified) (3 diffs)
-
src/SynTree/Expression.h (modified) (4 diffs)
-
src/SynTree/Mutator.cc (modified) (2 diffs)
-
src/SynTree/Visitor.cc (modified) (2 diffs)
-
src/libcfa/iostream.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
doc/LaTeXmacros/common.tex
r077810d r9d944b2 42 42 \newcommand{\CCfourteen}{\rm C\kern-.1em\hbox{+\kern-.25em+}14\xspace} % C++14 symbolic name 43 43 \newcommand{\CCseventeen}{\rm C\kern-.1em\hbox{+\kern-.25em+}17\xspace} % C++17 symbolic name 44 \newcommand{\CCtwenty}{\rm C\kern-.1em\hbox{+\kern-.25em+}20} % C++20 symbolic name45 44 \newcommand{\Celeven}{C11\xspace} % C11 symbolic name 46 45 \newcommand{\Csharp}{C\raisebox{0.4ex}{\#}\xspace} % C# symbolic name … … 201 200 \newcommand{\opt}{$_{opt}$\ } 202 201 203 \usepackage{varioref} % extended references204 202 % adjust varioref package with default "section" and "page" titles, and optional title with faraway page numbers 205 203 % \VRef{label} => Section 2.7, \VPageref{label} => page 17 … … 253 251 _Bool,catch,catchResume,choose,_Complex,__complex,__complex__,__const,__const__,disable,dtype,enable,__extension__, 254 252 fallthrough,fallthru,finally,forall,ftype,_Generic,_Imaginary,inline,__label__,lvalue,_Noreturn,one_t,otype,restrict,_Static_assert, 255 _Thread_local,throw,throwResume,trait,try,t type,typeof,__typeof,__typeof__,zero_t},253 _Thread_local,throw,throwResume,trait,try,typeof,__typeof,__typeof__,zero_t}, 256 254 }% 257 255 -
doc/generic_types/generic_types.tex
r077810d r9d944b2 148 148 \label{sec:poly-fns} 149 149 150 \CFA{}'s polymorphism was originally formalized by \citet{Ditchfield92}, and first implemented by \citet{Bilson03}. The signature feature of \CFA{} is parametric-polymorphic functions; such functions are written using a @forall@ clause (which gives the language its name): 150 \CFA{}'s polymorphism was originally formalized by \citet{Ditchfield92}, and first implemented by \citet{Bilson03}. The signature feature of \CFA{} is parametric-polymorphic functions; such functions are written using a @forall@ clause (which gives the language its name): 151 151 \begin{lstlisting} 152 152 forall(otype T) … … 174 174 forall(otype S | { S ?+?(S, S); }) 175 175 S twice(S x) { return x + x; } // (2) 176 \end{lstlisting} 177 This version of @twice@ works for any type @S@ that has an addition operator defined for it, and it could have been used to satisfy the type assertion on @four_times@. 176 \end{lstlisting} 177 This version of @twice@ works for any type @S@ that has an addition operator defined for it, and it could have been used to satisfy the type assertion on @four_times@. 178 178 The translator accomplishes this polymorphism by creating a wrapper function calling @twice // (2)@ with @S@ bound to @double@, then providing this wrapper function to @four_times@\footnote{\lstinline@twice // (2)@ could also have had a type parameter named \lstinline@T@; \CFA{} specifies renaming of the type parameters, which would avoid the name conflict with the type variable \lstinline@T@ of \lstinline@four_times@.}. 179 179 … … 196 196 forall(otype M | has_magnitude(M)) 197 197 M max_magnitude( M a, M b ) { 198 return abs(a) < abs(b) ? b : a; 198 return abs(a) < abs(b) ? b : a; 199 199 } 200 200 \end{lstlisting} … … 213 213 Given the information provided for an @otype@, variables of polymorphic type can be treated as if they were a complete struct type -- they can be stack-allocated using the @alloca@ compiler builtin, default or copy-initialized, assigned, and deleted. As an example, the @abs@ function above produces generated code something like the following (simplified for clarity and brevity): 214 214 \begin{lstlisting} 215 void abs( size_t _sizeof_M, size_t _alignof_M, 216 void (*_ctor_M)(void*), void (*_copy_M)(void*, void*), 217 void (*_assign_M)(void*, void*), void (*_dtor_M)(void*), 218 bool (*_lt_M)(void*, void*), void (*_neg_M)(void*, void*), 219 void (*_ctor_M_zero)(void*, int), 215 void abs( size_t _sizeof_M, size_t _alignof_M, 216 void (*_ctor_M)(void*), void (*_copy_M)(void*, void*), 217 void (*_assign_M)(void*, void*), void (*_dtor_M)(void*), 218 bool (*_lt_M)(void*, void*), void (*_neg_M)(void*, void*), 219 void (*_ctor_M_zero)(void*, int), 220 220 void* m, void* _rtn ) { // polymorphic parameter and return passed as void* 221 221 // M zero = { 0 }; … … 223 223 _ctor_M_zero(zero, 0); // initialize using zero_t constructor 224 224 // return m < zero ? -m : m; 225 void *_tmp = alloca(_sizeof_M) ;225 void *_tmp = alloca(_sizeof_M) 226 226 _copy_M( _rtn, // copy-initialize return value 227 227 _lt_M( m, zero ) ? // check condition … … 323 323 In some cases the offset arrays cannot be statically generated. For instance, modularity is generally provided in C by including an opaque forward-declaration of a struct and associated accessor and mutator routines in a header file, with the actual implementations in a separately-compiled \texttt{.c} file. \CFA{} supports this pattern for generic types, and in this instance the caller does not know the actual layout or size of the dynamic generic type, and only holds it by pointer. The \CFA{} translator automatically generates \emph{layout functions} for cases where the size, alignment, and offset array of a generic struct cannot be passed in to a function from that function's caller. These layout functions take as arguments pointers to size and alignment variables and a caller-allocated array of member offsets, as well as the size and alignment of all @sized@ parameters to the generic struct (un-@sized@ parameters are forbidden from the language from being used in a context that affects layout). Results of these layout functions are cached so that they are only computed once per type per function.%, as in the example below for @pair@. 324 324 % \begin{lstlisting} 325 % static inline void _layoutof_pair(size_t* _szeof_pair, size_t* _alignof_pair, size_t* _offsetof_pair, 325 % static inline void _layoutof_pair(size_t* _szeof_pair, size_t* _alignof_pair, size_t* _offsetof_pair, 326 326 % size_t _szeof_R, size_t _alignof_R, size_t _szeof_S, size_t _alignof_S) { 327 327 % *_szeof_pair = 0; // default values … … 332 332 % *_szeof_pair += _szeof_R; 333 333 % if ( *_alignof_pair < _alignof_R ) *_alignof_pair = _alignof_R; 334 334 335 335 % // padding, offset, size, and alignment of second field 336 336 % if ( *_szeof_pair & (_alignof_S - 1) ) … … 754 754 f(x.field_0, (_tuple2){ x.field_1, 'z' }); 755 755 \end{lstlisting} 756 Note that due to flattening, @x@ used in the argument position is converted into the list of its fields. In the call to @f@, the second and third argument components are structured into a tuple argument. Similarly, tuple member expressions are recursively expanded into a list of member access expressions.756 Note that due to flattening, @x@ used in the argument position is converted into the list of its fields. In the call to @f@, a the second and third argument components are structured into a tuple argument. Similarly, tuple member expressions are recursively expanded into a list of member access expressions. 757 757 758 758 Expressions that may contain side effects are made into \emph{unique expressions} before being expanded by the flattening conversion. Each unique expression is assigned an identifier and is guaranteed to be executed exactly once: … … 774 774 ); 775 775 \end{lstlisting} 776 Since argument evaluation order is not specified by the C programming language, this scheme is built to work regardless of evaluation order. The first time a unique expression is executed, the actual expression is evaluated and the accompanying boolean is setto true. Every subsequent evaluation of the unique expression then results in an access to the stored result of the actual expression. Tuple member expressions also take advantage of unique expressions in the case of possible impurity.776 Since argument evaluation order is not specified by the C programming language, this scheme is built to work regardless of evaluation order. The first time a unique expression is executed, the actual expression is evaluated and the accompanying boolean is true to true. Every subsequent evaluation of the unique expression then results in an access to the stored result of the actual expression. Tuple member expressions also take advantage of unique expressions in the case of possible impurity. 777 777 778 778 Currently, the \CFA{} translator has a very broad, imprecise definition of impurity, where any function call is assumed to be impure. This notion could be made more precise for certain intrinsic, auto-generated, and builtin functions, and could analyze function bodies when they are available to recursively detect impurity, to eliminate some unique expressions. -
doc/rob_thesis/ctordtor.tex
r077810d r9d944b2 135 135 % at the global scope (which is likely the most common case) 136 136 % * [9] 137 138 % Move semantics 139 % * <ongoing discussion about this. this will be filled in 140 % once we come to a consensus> 137 141 138 142 % Changes to polymorphic type classes -
doc/rob_thesis/tuples.tex
r077810d r9d944b2 615 615 \end{cfacode} 616 616 Note that due to flattening, @x@ used in the argument position is converted into the list of its fields. 617 In the call to @f@, the second and third argument components are structured into a tuple argument.617 In the call to @f@, a the second and third argument components are structured into a tuple argument. 618 618 619 619 Expressions which may contain side effects are made into \emph{unique expressions} before being expanded by the flattening conversion. … … 643 643 \end{cfacode} 644 644 Since argument evaluation order is not specified by the C programming language, this scheme is built to work regardless of evaluation order. 645 The first time a unique expression is executed, the actual expression is evaluated and the accompanying boolean is setto true.645 The first time a unique expression is executed, the actual expression is evaluated and the accompanying boolean is true to true. 646 646 Every subsequent evaluation of the unique expression then results in an access to the stored result of the actual expression. 647 647 … … 1299 1299 Thunks 0 through 3 provide wrappers for the @otype@ parameters for @const char *@, while @_thunk4@ translates a call to @print([int, const char *])@ into a call to @print_variadic(int, [const char *])@. 1300 1300 This all builds to a call to @print_variadic@, with the appropriate copy construction of the tuple argument. 1301 1302 \section{Future Work} -
src/CodeGen/CodeGenerator.cc
r077810d r9d944b2 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 30 16:38:01 201713 // Update Count : 48 212 // Last Modified On : Fri Mar 17 09:06:01 2017 13 // Update Count : 481 14 14 // 15 15 … … 674 674 675 675 void CodeGenerator::visit( CompoundLiteralExpr *compLitExpr ) { 676 assert( compLitExpr->get_ result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) );677 output << "(" << genType( compLitExpr->get_ result(), "", pretty ) << ")";676 assert( compLitExpr->get_type() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) ); 677 output << "(" << genType( compLitExpr->get_type(), "", pretty ) << ")"; 678 678 compLitExpr->get_initializer()->accept( *this ); 679 679 } -
src/InitTweak/FixInit.cc
r077810d r9d944b2 738 738 stmtsToAddAfter.push_back( ifStmt ); 739 739 740 Statement * dtor = ctorInit->get_dtor(); 741 objDecl->set_init( NULL ); 742 ctorInit->set_ctor( NULL ); 743 ctorInit->set_dtor( nullptr ); 744 if ( dtor ) { 740 if ( ctorInit->get_dtor() ) { 745 741 // if the object has a non-trivial destructor, have to 746 742 // hoist it and the object into the global space and 747 743 // call the destructor function with atexit. 748 744 749 Statement * dtorStmt = dtor->clone();745 Statement * dtorStmt = ctorInit->get_dtor()->clone(); 750 746 751 747 // void __objName_dtor_atexitN(...) {...} … … 776 772 objDecl->set_mangleName( SymTab::Mangler::mangle( objDecl ) ); 777 773 774 objDecl->set_init( NULL ); 775 ctorInit->set_ctor( NULL ); 776 delete ctorInit; 777 778 778 // xxx - temporary hack: need to return a declaration, but want to hoist the current object out of this scope 779 779 // create a new object which is never used 780 780 static UniqueName dummyNamer( "_dummy" ); 781 781 ObjectDecl * dummy = new ObjectDecl( dummyNamer.newName(), Type::StorageClasses( Type::Static ), LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), 0, std::list< Attribute * >{ new Attribute("unused") } ); 782 delete ctorInit;783 782 return dummy; 784 783 } -
src/InitTweak/GenInit.cc
r077810d r9d944b2 294 294 handleDWT( objDecl ); 295 295 // hands off if @=, extern, builtin, etc. 296 // even if unmanaged, try to construct global or static if initializer is not constexpr, since this is not legal C297 if ( tryConstruct( objDecl ) && ( isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init()) ) ) ) {296 // if global but initializer is not constexpr, always try to construct, since this is not legal C 297 if ( ( tryConstruct( objDecl ) && isManaged( objDecl ) ) || (! inFunction && ! isConstExpr( objDecl->get_init() ) ) ) { 298 298 // constructed objects cannot be designated 299 if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=. \n", objDecl );299 if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.", objDecl ); 300 300 // constructed objects should not have initializers nested too deeply 301 301 if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl ); -
src/Parser/ExpressionNode.cc
r077810d r9d944b2 10 10 // Created On : Sat May 16 13:17:07 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 30 17:02:46201713 // Update Count : 5 1512 // Last Modified On : Sat Mar 4 06:58:47 2017 13 // Update Count : 509 14 14 // 15 15 … … 356 356 // these types do not have associated type information 357 357 } else if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( newDecl ) ) { 358 if ( newDeclStructDecl->has_body() ) { 359 return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl ), maybeMoveBuild< Initializer >(kids) ); 360 } else { 361 return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 362 } // if 358 return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 363 359 } else if ( UnionDecl * newDeclUnionDecl = dynamic_cast< UnionDecl * >( newDecl ) ) { 364 if ( newDeclUnionDecl->has_body() ) { 365 return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl ), maybeMoveBuild< Initializer >(kids) ); 366 } else { 367 return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 368 } // if 360 return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 369 361 } else if ( EnumDecl * newDeclEnumDecl = dynamic_cast< EnumDecl * >( newDecl ) ) { 370 if ( newDeclEnumDecl->has_body() ) { 371 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl ), maybeMoveBuild< Initializer >(kids) ); 372 } else { 373 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 374 } // if 362 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 375 363 } else { 376 364 assert( false ); -
src/Parser/parser.yy
r077810d r9d944b2 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 30 15:42:32 201713 // Update Count : 231 812 // Last Modified On : Fri Mar 17 15:42:22 2017 13 // Update Count : 2317 14 14 // 15 15 … … 423 423 | postfix_expression DECR 424 424 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::DecrPost, $1 ) ); } 425 | '(' type_name_no_function ')' '{' initializer_list comma_opt '}' // C99 , compound-literal425 | '(' type_name_no_function ')' '{' initializer_list comma_opt '}' // C99 426 426 { $$ = new ExpressionNode( build_compoundLiteral( $2, new InitializerNode( $5, true ) ) ); } 427 427 | postfix_expression '{' argument_expression_list '}' // CFA -
src/SymTab/Indexer.cc
r077810d r9d944b2 10 10 // Created On : Sun May 17 21:37:33 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Mar 30 16:38:47201713 // Update Count : 1 912 // Last Modified On : Tue Mar 14 08:07:34 2017 13 // Update Count : 17 14 14 // 15 15 … … 483 483 void Indexer::visit( CompoundLiteralExpr *compLitExpr ) { 484 484 acceptNewScope( compLitExpr->get_result(), *this ); 485 maybeAccept( compLitExpr->get_type(), *this ); 485 486 maybeAccept( compLitExpr->get_initializer(), *this ); 486 487 } -
src/SymTab/Validate.cc
r077810d r9d944b2 10 10 // Created On : Sun May 17 21:50:04 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 30 16:50:13201713 // Update Count : 35 712 // Last Modified On : Thu Mar 16 16:39:15 2017 13 // Update Count : 353 14 14 // 15 15 … … 222 222 CompoundLiteral compoundliteral; 223 223 224 EliminateTypedef::eliminateTypedef( translationUnit ); 224 225 HoistStruct::hoistStruct( translationUnit ); 225 EliminateTypedef::eliminateTypedef( translationUnit );226 226 ReturnTypeFixer::fix( translationUnit ); // must happen before autogen 227 227 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions … … 824 824 static UniqueName indexName( "_compLit" ); 825 825 826 ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, 0, compLitExpr->get_ result(), compLitExpr->get_initializer() );827 compLitExpr->set_ result( 0 );826 ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, 0, compLitExpr->get_type(), compLitExpr->get_initializer() ); 827 compLitExpr->set_type( 0 ); 828 828 compLitExpr->set_initializer( 0 ); 829 829 delete compLitExpr; -
src/SynTree/Expression.cc
r077810d r9d944b2 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 30 16:41:13201713 // Update Count : 5 212 // Last Modified On : Fri Mar 17 09:42:04 2017 13 // Update Count : 51 14 14 // 15 15 … … 571 571 572 572 573 CompoundLiteralExpr::CompoundLiteralExpr( Type * type, Initializer * initializer ) : initializer( initializer ) {573 CompoundLiteralExpr::CompoundLiteralExpr( Type * type, Initializer * initializer ) : type( type ), initializer( initializer ) { 574 574 assert( type && initializer ); 575 set_result( type );576 } 577 578 CompoundLiteralExpr::CompoundLiteralExpr( const CompoundLiteralExpr &other ) : Expression( other ), initializer( other.initializer->clone() ) {}575 set_result( type->clone() ); 576 } 577 578 CompoundLiteralExpr::CompoundLiteralExpr( const CompoundLiteralExpr &other ) : Expression( other ), type( other.type->clone() ), initializer( other.initializer->clone() ) {} 579 579 580 580 CompoundLiteralExpr::~CompoundLiteralExpr() { 581 581 delete initializer; 582 delete type; 582 583 } 583 584 … … 585 586 os << "Compound Literal Expression: " << std::endl; 586 587 os << std::string( indent+2, ' ' ); 587 get_result()->print( os, indent + 2 );588 type->print( os, indent + 2 ); 588 589 os << std::string( indent+2, ' ' ); 589 590 initializer->print( os, indent + 2 ); -
src/SynTree/Expression.h
r077810d r9d944b2 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 30 16:44:00201713 // Update Count : 4112 // Last Modified On : Sat Jan 14 14:37:54 2017 13 // Update Count : 37 14 14 // 15 15 … … 35 35 36 36 Type *& get_result() { return result; } 37 const Type * get_result() const { return result; }38 37 void set_result( Type * newValue ) { result = newValue; } 39 38 bool has_result() const { return result != nullptr; } … … 587 586 virtual ~CompoundLiteralExpr(); 588 587 588 Type * get_type() const { return type; } 589 void set_type( Type * t ) { type = t; } 590 589 591 Initializer * get_initializer() const { return initializer; } 590 592 void set_initializer( Initializer * i ) { initializer = i; } … … 595 597 virtual void print( std::ostream & os, int indent = 0 ) const; 596 598 private: 599 Type * type; 597 600 Initializer * initializer; 598 601 }; -
src/SynTree/Mutator.cc
r077810d r9d944b2 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 30 16:45:19201713 // Update Count : 2 212 // Last Modified On : Thu Feb 16 15:02:23 2017 13 // Update Count : 21 14 14 // 15 15 … … 369 369 compLitExpr->set_env( maybeMutate( compLitExpr->get_env(), *this ) ); 370 370 compLitExpr->set_result( maybeMutate( compLitExpr->get_result(), *this ) ); 371 compLitExpr->set_type( maybeMutate( compLitExpr->get_type(), *this ) ); 371 372 compLitExpr->set_initializer( maybeMutate( compLitExpr->get_initializer(), *this ) ); 372 373 return compLitExpr; -
src/SynTree/Visitor.cc
r077810d r9d944b2 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 30 16:45:25 201713 // Update Count : 2 412 // Last Modified On : Thu Feb 16 15:01:25 2017 13 // Update Count : 23 14 14 // 15 15 … … 292 292 void Visitor::visit( CompoundLiteralExpr *compLitExpr ) { 293 293 maybeAccept( compLitExpr->get_result(), *this ); 294 maybeAccept( compLitExpr->get_type(), *this ); 294 295 maybeAccept( compLitExpr->get_initializer(), *this ); 295 296 } -
src/libcfa/iostream.c
r077810d r9d944b2 154 154 ostype * ?|?( ostype * os, const char * cp ) { 155 155 enum { Open = 1, Close, OpenClose }; 156 static const unsigned char mask[256] @= {156 static const unsigned char mask[256] = { 157 157 // opening delimiters, no space after 158 158 ['('] : Open, ['['] : Open, ['{'] : Open,
Note:
See TracChangeset
for help on using the changeset viewer.