+// input/output stream operators and manipulators
+
+static int my_ios_index()
+{
+ static int i = std::ios_base::xalloc();
+ return i;
+}
+
+// Stream format gets copied or destroyed
+static void my_ios_callback(std::ios_base::event ev, std::ios_base & s, int i)
+{
+ print_context *p = static_cast<print_context *>(s.pword(i));
+ if (ev == std::ios_base::erase_event) {
+ delete p;
+ s.pword(i) = 0;
+ } else if (ev == std::ios_base::copyfmt_event && p != 0)
+ s.pword(i) = p->duplicate();
+}
+
+enum {
+ callback_registered = 1
+};
+
+// Get print_context associated with stream, may return 0 if no context has
+// been associated yet
+static inline print_context *get_print_context(std::ios_base & s)
+{
+ return static_cast<print_context *>(s.pword(my_ios_index()));
+}
+
+// Set print_context associated with stream, retain options
+static void set_print_context(std::ios_base & s, const print_context & c)
+{
+ int i = my_ios_index();
+ long flags = s.iword(i);
+ if (!(flags & callback_registered)) {
+ s.register_callback(my_ios_callback, i);
+ s.iword(i) = flags | callback_registered;
+ }
+ print_context *p = static_cast<print_context *>(s.pword(i));
+ unsigned options = p ? p->options : c.options;
+ delete p;
+ p = c.duplicate();
+ p->options = options;
+ s.pword(i) = p;
+}
+
+// Get options for print_context associated with stream
+static inline unsigned get_print_options(std::ios_base & s)
+{
+ print_context *p = get_print_context(s);
+ return p ? p->options : 0;
+}
+
+// Set options for print_context associated with stream
+static void set_print_options(std::ostream & s, unsigned options)
+{
+ print_context *p = get_print_context(s);
+ if (p == 0)
+ set_print_context(s, print_dflt(s, options));
+ else
+ p->options = options;
+}