1 /* GNU Objective C Runtime initialization
2 Copyright (C) 1993, 1995, 1996, 1997, 2002, 2009
3 Free Software Foundation, Inc.
4 Contributed by Kresten Krab Thorup
5 +load support contributed by Ovidiu Predescu <ovidiu@net-community.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under the
10 terms of the GNU General Public License as published by the Free Software
11 Foundation; either version 3, or (at your option) any later version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
27 #include "objc-private/common.h"
28 #include "objc/objc.h"
29 #include "objc/objc-api.h"
31 #include "objc/hash.h"
32 #include "objc/objc-list.h"
33 #include "objc-private/runtime.h"
35 /* The version number of this runtime. This must match the number
36 defined in gcc (objc-act.c). */
37 #define OBJC_VERSION 8
38 #define PROTOCOL_VERSION 2
40 /* This list contains all modules currently loaded into the runtime. */
41 static struct objc_list *__objc_module_list = 0; /* !T:MUTEX */
43 /* This list contains all proto_list's not yet assigned class links. */
44 static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */
46 /* List of unresolved static instances. */
47 static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
49 /* Global runtime "write" mutex. */
50 objc_mutex_t __objc_runtime_mutex = 0;
52 /* Number of threads that are alive. */
53 int __objc_runtime_threads_alive = 1; /* !T:MUTEX */
55 /* Check compiler vs runtime version. */
56 static void init_check_module_version (Module_t);
58 /* Assign isa links to protos. */
59 static void __objc_init_protocols (struct objc_protocol_list *protos);
61 /* Add protocol to class. */
62 static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
64 /* This is a hook which is called by __objc_exec_class every time a
65 class or a category is loaded into the runtime. This may e.g. help
66 a dynamic loader determine the classes that have been loaded when
67 an object file is dynamically linked in. */
68 void (*_objc_load_callback) (Class class, Category *category); /* !T:SAFE */
70 /* Is all categories/classes resolved? */
71 BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
74 __sel_register_typed_name (const char *name, const char *types,
75 struct objc_selector *orig, BOOL is_const);
77 /* Sends +load to all classes and categories in certain situations. */
78 static void objc_send_load (void);
80 /* Inserts all the classes defined in module in a tree of classes that
81 resembles the class hierarchy. This tree is traversed in preorder
82 and the classes in its nodes receive the +load message if these
83 methods were not executed before. The algorithm ensures that when
84 the +load method of a class is executed all the superclasses have
85 been already received the +load message. */
86 static void __objc_create_classes_tree (Module_t module);
88 static void __objc_call_callback (Module_t module);
90 /* A special version that works only before the classes are completely
91 installed in the runtime. */
92 static BOOL class_is_subclass_of_class (Class class, Class superclass);
94 typedef struct objc_class_tree {
96 struct objc_list *subclasses; /* `head' is pointer to an objc_class_tree */
99 /* This is a linked list of objc_class_tree trees. The head of these
100 trees are root classes (their super class is Nil). These different
101 trees represent different class hierarchies. */
102 static struct objc_list *__objc_class_tree_list = NULL;
104 /* Keeps the +load methods who have been already executed. This hash
105 should not be destroyed during the execution of the program. */
106 static cache_ptr __objc_load_methods = NULL;
108 /* This function is used when building the class tree used to send
109 ordinately the +load message to all classes needing it. The tree
110 is really needed so that superclasses will get the message before
113 This tree will contain classes which are being loaded (or have just
114 being loaded), and whose super_class pointers have not yet been
115 resolved. This implies that their super_class pointers point to a
116 string with the name of the superclass; when the first message is
117 sent to the class (/an object of that class) the class links will
118 be resolved, which will replace the super_class pointers with
119 pointers to the actual superclasses.
121 Unfortunately, the tree might also contain classes which had been
122 loaded previously, and whose class links have already been
125 This function returns the superclass of a class in both cases, and
126 can be used to build the determine the class relationships while
129 static Class class_superclass_of_class (Class class)
131 char *super_class_name;
133 /* If the class links have been resolved, use the resolved
135 if (CLS_ISRESOLV (class))
136 return class->super_class;
138 /* Else, 'class' has not yet been resolved. This means that its
139 * super_class pointer is really the name of the super class (rather
140 * than a pointer to the actual superclass). */
141 super_class_name = (char *)class->super_class;
143 /* Return Nil for a root class. */
144 if (super_class_name == NULL)
147 /* Lookup the superclass of non-root classes. */
148 return objc_lookup_class (super_class_name);
152 /* Creates a tree of classes whose topmost class is directly inherited
153 from `upper' and the bottom class in this tree is
154 `bottom_class'. The classes in this tree are super classes of
155 `bottom_class'. `subclasses' member of each tree node point to the
156 next subclass tree node. */
158 static objc_class_tree *
159 create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
161 Class superclass = bottom_class->super_class ?
162 objc_lookup_class ((char *) bottom_class->super_class)
165 objc_class_tree *tree, *prev;
167 DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
168 DEBUG_PRINTF ("bottom_class = %s, upper = %s\n",
169 (bottom_class ? bottom_class->name : NULL),
170 (upper ? upper->name : NULL));
172 tree = prev = objc_calloc (1, sizeof (objc_class_tree));
173 prev->class = bottom_class;
175 while (superclass != upper)
177 tree = objc_calloc (1, sizeof (objc_class_tree));
178 tree->class = superclass;
179 tree->subclasses = list_cons (prev, tree->subclasses);
180 superclass = class_superclass_of_class (superclass);
187 /* Insert the `class' into the proper place in the `tree' class
188 hierarchy. This function returns a new tree if the class has been
189 successfully inserted into the tree or NULL if the class is not
190 part of the classes hierarchy described by `tree'. This function is
191 private to objc_tree_insert_class (), you should not call it
194 static objc_class_tree *
195 __objc_tree_insert_class (objc_class_tree *tree, Class class)
197 DEBUG_PRINTF ("__objc_tree_insert_class: tree = %x, class = %s\n",
201 return create_tree_of_subclasses_inherited_from (class, NULL);
202 else if (class == tree->class)
204 /* `class' has been already inserted */
205 DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
208 else if (class_superclass_of_class (class) == tree->class)
210 /* If class is a direct subclass of tree->class then add class to the
211 list of subclasses. First check to see if it wasn't already
213 struct objc_list *list = tree->subclasses;
214 objc_class_tree *node;
218 /* Class has been already inserted; do nothing just return
220 if (((objc_class_tree *) list->head)->class == class)
222 DEBUG_PRINTF ("2. class %s was previously inserted\n",
229 /* Create a new node class and insert it into the list of subclasses */
230 node = objc_calloc (1, sizeof (objc_class_tree));
232 tree->subclasses = list_cons (node, tree->subclasses);
233 DEBUG_PRINTF ("3. class %s inserted\n", class->name);
238 /* The class is not a direct subclass of tree->class. Search for
239 class's superclasses in the list of subclasses. */
240 struct objc_list *subclasses = tree->subclasses;
242 /* Precondition: the class must be a subclass of tree->class;
243 otherwise return NULL to indicate our caller that it must
244 take the next tree. */
245 if (! class_is_subclass_of_class (class, tree->class))
248 for (; subclasses != NULL; subclasses = subclasses->tail)
250 Class aClass = ((objc_class_tree *) (subclasses->head))->class;
252 if (class_is_subclass_of_class (class, aClass))
254 /* If we found one of class's superclasses we insert the
255 class into its subtree and return the original tree
256 since nothing has been changed. */
258 = __objc_tree_insert_class (subclasses->head, class);
259 DEBUG_PRINTF ("4. class %s inserted\n", class->name);
264 /* We haven't found a subclass of `class' in the `subclasses'
265 list. Create a new tree of classes whose topmost class is a
266 direct subclass of tree->class. */
268 objc_class_tree *new_tree
269 = create_tree_of_subclasses_inherited_from (class, tree->class);
270 tree->subclasses = list_cons (new_tree, tree->subclasses);
271 DEBUG_PRINTF ("5. class %s inserted\n", class->name);
277 /* This function inserts `class' in the right tree hierarchy classes. */
280 objc_tree_insert_class (Class class)
282 struct objc_list *list_node;
283 objc_class_tree *tree;
285 list_node = __objc_class_tree_list;
288 tree = __objc_tree_insert_class (list_node->head, class);
291 list_node->head = tree;
295 list_node = list_node->tail;
298 /* If the list was finished but the class hasn't been inserted,
302 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
303 __objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
307 /* Traverse tree in preorder. Used to send +load. */
310 objc_preorder_traverse (objc_class_tree *tree,
312 void (*function) (objc_class_tree *, int))
314 struct objc_list *node;
316 (*function) (tree, level);
317 for (node = tree->subclasses; node; node = node->tail)
318 objc_preorder_traverse (node->head, level + 1, function);
321 /* Traverse tree in postorder. Used to destroy a tree. */
324 objc_postorder_traverse (objc_class_tree *tree,
326 void (*function) (objc_class_tree *, int))
328 struct objc_list *node;
330 for (node = tree->subclasses; node; node = node->tail)
331 objc_postorder_traverse (node->head, level + 1, function);
332 (*function) (tree, level);
335 /* Used to print a tree class hierarchy. */
339 __objc_tree_print (objc_class_tree *tree, int level)
343 for (i = 0; i < level; i++)
345 printf ("%s\n", tree->class->name);
349 /* Walks on a linked list of methods in the reverse order and executes
350 all the methods corresponding to `op' selector. Walking in the
351 reverse order assures the +load of class is executed first and then
352 +load of categories because of the way in which categories are
353 added to the class methods. */
356 __objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
363 /* First execute the `op' message in the following method lists */
364 __objc_send_message_in_list (method_list->method_next, class, op);
366 /* Search the method list. */
367 for (i = 0; i < method_list->method_count; i++)
369 Method_t mth = &method_list->method_list[i];
371 if (mth->method_name && sel_eq (mth->method_name, op)
372 && ! objc_hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
374 /* Add this method into the +load hash table */
375 objc_hash_add (&__objc_load_methods,
379 DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
381 /* The method was found and wasn't previously executed. */
382 (*mth->method_imp) ((id)class, mth->method_name);
390 __objc_send_load (objc_class_tree *tree,
391 int level __attribute__ ((__unused__)))
393 static SEL load_sel = 0;
394 Class class = tree->class;
395 MethodList_t method_list = class->class_pointer->methods;
398 load_sel = sel_register_name ("load");
400 __objc_send_message_in_list (method_list, class, load_sel);
404 __objc_destroy_class_tree_node (objc_class_tree *tree,
405 int level __attribute__ ((__unused__)))
410 /* This is used to check if the relationship between two classes
411 before the runtime completely installs the classes. */
414 class_is_subclass_of_class (Class class, Class superclass)
416 for (; class != Nil;)
418 if (class == superclass)
420 class = class_superclass_of_class (class);
426 /* This list contains all the classes in the runtime system for whom
427 their superclasses are not yet known to the runtime. */
428 static struct objc_list *unresolved_classes = 0;
430 /* Extern function used to reference the Object and NXConstantString
433 extern void __objc_force_linking (void);
436 __objc_force_linking (void)
438 extern void __objc_linking (void);
442 /* Run through the statics list, removing modules as soon as all its
443 statics have been initialized. */
446 objc_init_statics (void)
448 struct objc_list **cell = &uninitialized_statics;
449 struct objc_static_instances **statics_in_module;
451 objc_mutex_lock (__objc_runtime_mutex);
455 int module_initialized = 1;
457 for (statics_in_module = (*cell)->head;
458 *statics_in_module; statics_in_module++)
460 struct objc_static_instances *statics = *statics_in_module;
461 Class class = objc_lookup_class (statics->class_name);
464 module_initialized = 0;
465 /* Actually, the static's class_pointer will be NULL when we
466 haven't been here before. However, the comparison is to be
467 reminded of taking into account class posing and to think about
468 possible semantics... */
469 else if (class != statics->instances[0]->class_pointer)
473 for (inst = &statics->instances[0]; *inst; inst++)
475 (*inst)->class_pointer = class;
477 /* ??? Make sure the object will not be freed. With
478 refcounting, invoke `-retain'. Without refcounting, do
479 nothing and hope that `-free' will never be invoked. */
481 /* ??? Send the object an `-initStatic' or something to
482 that effect now or later on? What are the semantics of
483 statically allocated instances, besides the trivial
484 NXConstantString, anyway? */
488 if (module_initialized)
490 /* Remove this module from the uninitialized list. */
491 struct objc_list *this = *cell;
496 cell = &(*cell)->tail;
499 objc_mutex_unlock (__objc_runtime_mutex);
500 } /* objc_init_statics */
502 /* This function is called by constructor functions generated for each
503 module compiled. (_GLOBAL_$I$...) The purpose of this function is
504 to gather the module pointers so that they may be processed by the
505 initialization routines as soon as possible. */
508 __objc_exec_class (Module_t module)
510 /* Have we processed any constructors previously? This flag is used to
511 indicate that some global data structures need to be built. */
512 static BOOL previous_constructors = 0;
514 static struct objc_list *unclaimed_categories = 0;
516 /* The symbol table (defined in objc-api.h) generated by gcc */
517 Symtab_t symtab = module->symtab;
519 /* The statics in this module */
520 struct objc_static_instances **statics
521 = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
523 /* Entry used to traverse hash lists */
524 struct objc_list **cell;
526 /* The table of selector references for this module */
527 SEL selectors = symtab->refs;
532 DEBUG_PRINTF ("received module: %s\n", module->name);
534 /* check gcc version */
535 init_check_module_version (module);
537 /* On the first call of this routine, initialize some data structures. */
538 if (! previous_constructors)
540 /* Initialize thread-safe system */
541 __objc_init_thread_system ();
542 __objc_runtime_threads_alive = 1;
543 __objc_runtime_mutex = objc_mutex_allocate ();
545 __objc_init_selector_tables ();
546 __objc_init_class_tables ();
547 __objc_init_dispatch_tables ();
548 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
549 __objc_load_methods = objc_hash_new (128,
550 (hash_func_type)objc_hash_ptr,
552 previous_constructors = 1;
555 /* Save the module pointer for later processing. (not currently used) */
556 objc_mutex_lock (__objc_runtime_mutex);
557 __objc_module_list = list_cons (module, __objc_module_list);
559 /* Replace referenced selectors from names to SEL's. */
562 for (i = 0; selectors[i].sel_id; ++i)
564 const char *name, *type;
565 name = (char *) selectors[i].sel_id;
566 type = (char *) selectors[i].sel_types;
567 /* Constructors are constant static data so we can safely store
568 pointers to them in the runtime structures. is_const == YES */
569 __sel_register_typed_name (name, type,
570 (struct objc_selector *) &(selectors[i]),
575 /* Parse the classes in the load module and gather selector information. */
576 DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
577 for (i = 0; i < symtab->cls_def_cnt; ++i)
579 Class class = (Class) symtab->defs[i];
580 const char *superclass = (char *) class->super_class;
582 /* Make sure we have what we think. */
583 assert (CLS_ISCLASS (class));
584 assert (CLS_ISMETA (class->class_pointer));
585 DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
587 /* Initialize the subclass list to be NULL.
588 In some cases it isn't and this crashes the program. */
589 class->subclass_list = NULL;
591 /* Store the class in the class table and assign class numbers. */
592 __objc_add_class_to_hash (class);
594 /* Register all of the selectors in the class and meta class. */
595 __objc_register_selectors_from_class (class);
596 __objc_register_selectors_from_class ((Class) class->class_pointer);
598 /* Install the fake dispatch tables */
599 __objc_install_premature_dtable (class);
600 __objc_install_premature_dtable (class->class_pointer);
602 /* Register the instance methods as class methods, this is
603 only done for root classes. */
604 __objc_register_instance_methods_to_class (class);
606 if (class->protocols)
607 __objc_init_protocols (class->protocols);
609 /* Check to see if the superclass is known in this point. If it's not
610 add the class to the unresolved_classes list. */
611 if (superclass && ! objc_lookup_class (superclass))
612 unresolved_classes = list_cons (class, unresolved_classes);
615 /* Process category information from the module. */
616 for (i = 0; i < symtab->cat_def_cnt; ++i)
618 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
619 Class class = objc_lookup_class (category->class_name);
621 /* If the class for the category exists then append its methods. */
625 DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
629 /* Do instance methods. */
630 if (category->instance_methods)
631 class_add_method_list (class, category->instance_methods);
633 /* Do class methods. */
634 if (category->class_methods)
635 class_add_method_list ((Class) class->class_pointer,
636 category->class_methods);
638 if (category->protocols)
640 __objc_init_protocols (category->protocols);
641 __objc_class_add_protocols (class, category->protocols);
644 /* Register the instance methods as class methods, this is
645 only done for root classes. */
646 __objc_register_instance_methods_to_class (class);
650 /* The object to which the category methods belong can't be found.
651 Save the information. */
652 unclaimed_categories = list_cons (category, unclaimed_categories);
657 uninitialized_statics = list_cons (statics, uninitialized_statics);
658 if (uninitialized_statics)
659 objc_init_statics ();
661 /* Scan the unclaimed category hash. Attempt to attach any unclaimed
662 categories to objects. */
663 for (cell = &unclaimed_categories; *cell; )
665 Category_t category = (*cell)->head;
666 Class class = objc_lookup_class (category->class_name);
670 DEBUG_PRINTF ("attaching stored categories to object: %s\n",
673 list_remove_head (cell);
675 if (category->instance_methods)
676 class_add_method_list (class, category->instance_methods);
678 if (category->class_methods)
679 class_add_method_list ((Class) class->class_pointer,
680 category->class_methods);
682 if (category->protocols)
684 __objc_init_protocols (category->protocols);
685 __objc_class_add_protocols (class, category->protocols);
688 /* Register the instance methods as class methods, this is
689 only done for root classes. */
690 __objc_register_instance_methods_to_class (class);
693 cell = &(*cell)->tail;
696 if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
698 list_mapcar (unclaimed_proto_list,
699 (void (*) (void *))__objc_init_protocols);
700 list_free (unclaimed_proto_list);
701 unclaimed_proto_list = 0;
706 objc_mutex_unlock (__objc_runtime_mutex);
710 objc_send_load (void)
712 if (! __objc_module_list)
715 /* Try to find out if all the classes loaded so far also have their
716 superclasses known to the runtime. We suppose that the objects
717 that are allocated in the +load method are in general of a class
718 declared in the same module. */
719 if (unresolved_classes)
721 Class class = unresolved_classes->head;
723 while (objc_lookup_class ((char *) class->super_class))
725 list_remove_head (&unresolved_classes);
726 if (unresolved_classes)
727 class = unresolved_classes->head;
732 /* If we still have classes for whom we don't have yet their
733 super classes known to the runtime we don't send the +load
735 if (unresolved_classes)
739 /* Special check to allow creating and sending messages to constant
740 strings in +load methods. If these classes are not yet known,
741 even if all the other classes are known, delay sending of +load. */
742 if (! objc_lookup_class ("NXConstantString") ||
743 ! objc_lookup_class ("Object"))
746 /* Iterate over all modules in the __objc_module_list and call on
747 them the __objc_create_classes_tree function. This function
748 creates a tree of classes that resembles the class hierarchy. */
749 list_mapcar (__objc_module_list,
750 (void (*) (void *)) __objc_create_classes_tree);
752 while (__objc_class_tree_list)
755 objc_preorder_traverse (__objc_class_tree_list->head,
756 0, __objc_tree_print);
758 objc_preorder_traverse (__objc_class_tree_list->head,
759 0, __objc_send_load);
760 objc_postorder_traverse (__objc_class_tree_list->head,
761 0, __objc_destroy_class_tree_node);
762 list_remove_head (&__objc_class_tree_list);
765 list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback);
766 list_free (__objc_module_list);
767 __objc_module_list = NULL;
771 __objc_create_classes_tree (Module_t module)
773 /* The runtime mutex is locked in this point */
775 Symtab_t symtab = module->symtab;
778 /* Iterate thru classes defined in this module and insert them in
779 the classes tree hierarchy. */
780 for (i = 0; i < symtab->cls_def_cnt; i++)
782 Class class = (Class) symtab->defs[i];
784 objc_tree_insert_class (class);
789 __objc_call_callback (Module_t module)
791 /* The runtime mutex is locked in this point. */
793 Symtab_t symtab = module->symtab;
796 /* Iterate thru classes defined in this module and call the callback
798 for (i = 0; i < symtab->cls_def_cnt; i++)
800 Class class = (Class) symtab->defs[i];
802 /* Call the _objc_load_callback for this class. */
803 if (_objc_load_callback)
804 _objc_load_callback (class, 0);
807 /* Call the _objc_load_callback for categories. Don't register the
808 instance methods as class methods for categories to root classes
809 since they were already added in the class. */
810 for (i = 0; i < symtab->cat_def_cnt; i++)
812 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
813 Class class = objc_lookup_class (category->class_name);
815 if (_objc_load_callback)
816 _objc_load_callback (class, category);
820 /* Sanity check the version of gcc used to compile `module'. */
823 init_check_module_version (Module_t module)
825 if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
829 if (module->version > OBJC_VERSION)
830 code = OBJC_ERR_OBJC_VERSION;
831 else if (module->version < OBJC_VERSION)
832 code = OBJC_ERR_GCC_VERSION;
834 code = OBJC_ERR_MODULE_SIZE;
836 objc_error (nil, code, "Module %s version %d doesn't match runtime %d\n",
837 module->name, (int)module->version, OBJC_VERSION);
842 __objc_init_protocols (struct objc_protocol_list *protos)
845 static Class proto_class = 0;
850 objc_mutex_lock (__objc_runtime_mutex);
853 proto_class = objc_lookup_class ("Protocol");
857 unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
858 objc_mutex_unlock (__objc_runtime_mutex);
863 assert (protos->next == 0); /* only single ones allowed */
866 for (i = 0; i < protos->count; i++)
868 struct objc_protocol *aProto = protos->list[i];
869 if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
871 /* assign class pointer */
872 aProto->class_pointer = proto_class;
874 /* init super protocols */
875 __objc_init_protocols (aProto->protocol_list);
877 else if (protos->list[i]->class_pointer != proto_class)
879 objc_error (nil, OBJC_ERR_PROTOCOL_VERSION,
880 "Version %d doesn't match runtime protocol version %d\n",
881 (int) ((char *) protos->list[i]->class_pointer
887 objc_mutex_unlock (__objc_runtime_mutex);
891 __objc_class_add_protocols (Class class, struct objc_protocol_list *protos)
898 protos->next = class->protocols;
899 class->protocols = protos;