Exemplo n.º 1
0
static int
S_render_node(cmark_renderer *renderer,
	      cmark_node *node,
	      cmark_event_type ev_type,
	      int options)
{
	int list_number;
	char list_number_string[20];
	bool entering = (ev_type == CMARK_EVENT_ENTER);
	cmark_list_type list_type;
	const char* roman_numerals[] = { "", "i", "ii", "iii", "iv", "v",
	                                 "vi", "vii", "viii", "ix", "x"
	                               };

	// avoid warning about unused parameter:
	(void)(options);

	switch (node->type) {
	case CMARK_NODE_DOCUMENT:
		break;

	case CMARK_NODE_BLOCK_QUOTE:
		if (entering) {
			LIT("\\begin{quote}");
			CR();
		} else {
			LIT("\\end{quote}");
			BLANKLINE();
		}
		break;

	case CMARK_NODE_LIST:
		list_type = cmark_node_get_list_type(node);
		if (entering) {
			LIT("\\begin{");
			LIT(list_type == CMARK_ORDERED_LIST ?
			    "enumerate" : "itemize");
			LIT("}");
			CR();
			list_number = cmark_node_get_list_start(node);
			if (list_number > 1) {
				sprintf(list_number_string,
				         "%d", list_number);
				LIT("\\setcounter{enum");
				LIT((char *)roman_numerals[S_get_enumlevel(node)]);
				LIT("}{");
				OUT(list_number_string, false, NORMAL);
				LIT("}");
				CR();
			}
		} else {
			LIT("\\end{");
			LIT(list_type == CMARK_ORDERED_LIST ?
			    "enumerate" : "itemize");
			LIT("}");
			BLANKLINE();
		}
		break;

	case CMARK_NODE_ITEM:
		if (entering) {
			LIT("\\item ");
		} else {
			CR();
		}
		break;

	case CMARK_NODE_HEADER:
		if (entering) {
			switch (cmark_node_get_header_level(node)) {
			case 1:
				LIT("\\section");
				break;
			case 2:
				LIT("\\subsection");
				break;
			case 3:
				LIT("\\subsubsection");
				break;
			case 4:
				LIT("\\paragraph");
				break;
			case 5:
				LIT("\\subparagraph");
				break;
			}
			LIT("{");
		} else {
			LIT("}");
			BLANKLINE();
		}
		break;

	case CMARK_NODE_CODE_BLOCK:
		CR();
		LIT("\\begin{verbatim}");
		CR();
		OUT(cmark_node_get_literal(node), false, LITERAL);
		CR();
		LIT("\\end{verbatim}");
		BLANKLINE();
		break;

	case CMARK_NODE_HTML:
		break;

	case CMARK_NODE_HRULE:
		BLANKLINE();
		LIT("\\begin{center}\\rule{0.5\\linewidth}{\\linethickness}\\end{center}");
		BLANKLINE();
		break;

	case CMARK_NODE_PARAGRAPH:
		if (!entering) {
			BLANKLINE();
		}
		break;

	case CMARK_NODE_TEXT:
		OUT(cmark_node_get_literal(node), true, NORMAL);
		break;

	case CMARK_NODE_LINEBREAK:
		LIT("\\\\");
		CR();
		break;

	case CMARK_NODE_SOFTBREAK:
		if (renderer->width == 0) {
			CR();
		} else {
			OUT(" ", true, NORMAL);
		}
		break;

	case CMARK_NODE_CODE:
		LIT("\\texttt{");
		OUT(cmark_node_get_literal(node), false, NORMAL);
		LIT("}");
		break;

	case CMARK_NODE_INLINE_HTML:
		break;

	case CMARK_NODE_STRONG:
		if (entering) {
			LIT("\\textbf{");
		} else {
			LIT("}");
		}
		break;

	case CMARK_NODE_EMPH:
		if (entering) {
			LIT("\\emph{");
		} else {
			LIT("}");
		}
		break;

	case CMARK_NODE_LINK:
		if (entering) {
			const char* url = cmark_node_get_url(node);
			// requires \usepackage{hyperref}
			switch(get_link_type(node)) {
			case URL_AUTOLINK:
				LIT("\\url{");
				OUT(url, false, URL);
				break;
			case EMAIL_AUTOLINK:
				LIT("\\href{");
				OUT(url, false, URL);
				LIT("}\\nolinkurl{");
				break;
			case NORMAL_LINK:
				LIT("\\href{");
				OUT(url, false, URL);
				LIT("}{");
				break;
			case NO_LINK:
				LIT("{");  // error?
			}
		} else {
			LIT("}");
		}

		break;

	case CMARK_NODE_IMAGE:
		if (entering) {
			LIT("\\protect\\includegraphics{");
			// requires \include{graphicx}
			OUT(cmark_node_get_url(node), false, URL);
			LIT("}");
			return 0;
		}
		break;

	default:
		assert(false);
		break;
	}

	return 1;
}
Exemplo n.º 2
0
static int S_render_node(cmark_renderer *renderer, cmark_node *node,
                         cmark_event_type ev_type, int options) {
  int list_number;
  int enumlevel;
  char list_number_string[LIST_NUMBER_STRING_SIZE];
  bool entering = (ev_type == CMARK_EVENT_ENTER);
  cmark_list_type list_type;
  bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);

  // avoid warning about unused parameter:
  (void)(options);

  switch (node->type) {
  case CMARK_NODE_DOCUMENT:
    break;

  case CMARK_NODE_BLOCK_QUOTE:
    if (entering) {
      LIT("\\begin{quote}");
      CR();
    } else {
      LIT("\\end{quote}");
      BLANKLINE();
    }
    break;

  case CMARK_NODE_LIST:
    list_type = cmark_node_get_list_type(node);
    if (entering) {
      LIT("\\begin{");
      LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize");
      LIT("}");
      CR();
      list_number = cmark_node_get_list_start(node);
      if (list_number > 1) {
	enumlevel = S_get_enumlevel(node);
	// latex normally supports only five levels
	if (enumlevel >= 1 && enumlevel <= 5) {
          snprintf(list_number_string, LIST_NUMBER_STRING_SIZE, "%d",
                   list_number);
          LIT("\\setcounter{enum");
          switch(enumlevel) {
	  case 1: LIT("i"); break;
	  case 2: LIT("ii"); break;
	  case 3: LIT("iii"); break;
	  case 4: LIT("iv"); break;
	  case 5: LIT("v"); break;
	  default: LIT("i"); break;
	  }
          LIT("}{");
          OUT(list_number_string, false, NORMAL);
          LIT("}");
	}
        CR();
      }
    } else {
      LIT("\\end{");
      LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize");
      LIT("}");
      BLANKLINE();
    }
    break;

  case CMARK_NODE_ITEM:
    if (entering) {
      LIT("\\item ");
    } else {
      CR();
    }
    break;

  case CMARK_NODE_HEADING:
    if (entering) {
      switch (cmark_node_get_heading_level(node)) {
      case 1:
        LIT("\\section");
        break;
      case 2:
        LIT("\\subsection");
        break;
      case 3:
        LIT("\\subsubsection");
        break;
      case 4:
        LIT("\\paragraph");
        break;
      case 5:
        LIT("\\subparagraph");
        break;
      }
      LIT("{");
    } else {
      LIT("}");
      BLANKLINE();
    }
    break;

  case CMARK_NODE_CODE_BLOCK:
    CR();
    LIT("\\begin{verbatim}");
    CR();
    OUT(cmark_node_get_literal(node), false, LITERAL);
    CR();
    LIT("\\end{verbatim}");
    BLANKLINE();
    break;

  case CMARK_NODE_HTML_BLOCK:
    break;

  case CMARK_NODE_CUSTOM_BLOCK:
    CR();
    OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
        false, LITERAL);
    CR();
    break;

  case CMARK_NODE_THEMATIC_BREAK:
    BLANKLINE();
    LIT("\\begin{center}\\rule{0.5\\linewidth}{\\linethickness}\\end{center}");
    BLANKLINE();
    break;

  case CMARK_NODE_PARAGRAPH:
    if (!entering) {
      BLANKLINE();
    }
    break;

  case CMARK_NODE_TEXT:
    OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
    break;

  case CMARK_NODE_LINEBREAK:
    LIT("\\\\");
    CR();
    break;

  case CMARK_NODE_SOFTBREAK:
    if (options & CMARK_OPT_HARDBREAKS) {
      LIT("\\\\");
      CR();
    } else if (renderer->width == 0 && !(CMARK_OPT_NOBREAKS & options)) {
      CR();
    } else {
      OUT(" ", allow_wrap, NORMAL);
    }
    break;

  case CMARK_NODE_CODE:
    LIT("\\texttt{");
    OUT(cmark_node_get_literal(node), false, NORMAL);
    LIT("}");
    break;

  case CMARK_NODE_HTML_INLINE:
    break;

  case CMARK_NODE_CUSTOM_INLINE:
    OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
        false, LITERAL);
    break;

  case CMARK_NODE_STRONG:
    if (entering) {
      LIT("\\textbf{");
    } else {
      LIT("}");
    }
    break;

  case CMARK_NODE_EMPH:
    if (entering) {
      LIT("\\emph{");
    } else {
      LIT("}");
    }
    break;

  case CMARK_NODE_LINK:
    if (entering) {
      const char *url = cmark_node_get_url(node);
      // requires \usepackage{hyperref}
      switch (get_link_type(node)) {
      case URL_AUTOLINK:
        LIT("\\url{");
        OUT(url, false, URL);
        LIT("}");
        return 0; // Don't process further nodes to avoid double-rendering artefacts
      case EMAIL_AUTOLINK:
        LIT("\\href{");
        OUT(url, false, URL);
        LIT("}\\nolinkurl{");
        break;
      case NORMAL_LINK:
        LIT("\\href{");
        OUT(url, false, URL);
        LIT("}{");
        break;
      case INTERNAL_LINK:
        LIT("\\protect\\hyperlink{");
        OUT(url + 1, false, URL);
        LIT("}{");
        break;
      case NO_LINK:
        LIT("{"); // error?
      }
    } else {
      LIT("}");
    }

    break;

  case CMARK_NODE_IMAGE:
    if (entering) {
      LIT("\\protect\\includegraphics{");
      // requires \include{graphicx}
      OUT(cmark_node_get_url(node), false, URL);
      LIT("}");
      return 0;
    }
    break;

  default:
    assert(false);
    break;
  }

  return 1;
}
Exemplo n.º 3
0
void nl_bridge::update_vlans(rtnl_link *old_link, rtnl_link *new_link) {
  assert(sw);
  assert(bridge); // already checked

  rtnl_link_bridge_vlan *old_br_vlan, *new_br_vlan;
  rtnl_link *_link;

  if (old_link == nullptr) {
    // link added
    old_br_vlan = &empty_br_vlan;
    new_br_vlan = rtnl_link_bridge_get_port_vlan(new_link);
    _link = nl->get_link(rtnl_link_get_ifindex(new_link), AF_UNSPEC);
  } else if (new_link == nullptr) {
    // link deleted
    old_br_vlan = rtnl_link_bridge_get_port_vlan(old_link);
    new_br_vlan = &empty_br_vlan;
    _link = nl->get_link(rtnl_link_get_ifindex(old_link), AF_UNSPEC);
  } else {
    // link updated
    old_br_vlan = rtnl_link_bridge_get_port_vlan(old_link);
    new_br_vlan = rtnl_link_bridge_get_port_vlan(new_link);
    _link = nl->get_link(rtnl_link_get_ifindex(new_link), AF_UNSPEC);
  }

  if (old_br_vlan == nullptr) {
    old_br_vlan = &empty_br_vlan;
  }

  if (new_br_vlan == nullptr) {
    new_br_vlan = &empty_br_vlan;
  }

  if (_link == nullptr) {
    // XXX FIXME in case a vxlan has been deleted the vxlan_domain and
    // vxlan_dom_bitmap need an update, maybe this can be handled already from
    // the link_deleted of the vxlan itself?
    LOG(WARNING) << __FUNCTION__
                 << ": could not get parent link of bridge interface. This "
                    "case needs further checks if everything got already "
                    "deleted.";
    return;
  }

  // check for vid changes
  if (br_vlan_equal(old_br_vlan, new_br_vlan)) {
    VLOG(2) << __FUNCTION__ << ": vlans did not change";
    return;
  }

  link_type lt = get_link_type(_link);
  uint32_t pport_no = 0;
  uint32_t tunnel_id = -1;
  std::deque<rtnl_link *> bridge_ports;

  if (lt == LT_VXLAN) {
    assert(nl);
    nl->get_bridge_ports(rtnl_link_get_master(_link), &bridge_ports);

    if (vxlan->get_tunnel_id(_link, nullptr, &tunnel_id) != 0) {
      LOG(ERROR) << __FUNCTION__ << ": failed to get vni of link "
                 << OBJ_CAST(_link);
    }

  } else {
    pport_no = nl->get_port_id(rtnl_link_get_ifindex(_link));
    if (pport_no == 0) {
      LOG(ERROR) << __FUNCTION__
                 << ": invalid pport_no=0 of link: " << OBJ_CAST(_link);
      return;
    }
  }

  for (int k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) {
    int base_bit;
    uint32_t a = old_br_vlan->vlan_bitmap[k];
    uint32_t b = new_br_vlan->vlan_bitmap[k];
    uint32_t vlan_diff = a ^ b;

#if 0  // untagged change not yet implemented
    uint32_t c = old_br_vlan->untagged_bitmap[k];
    uint32_t d = new_br_vlan->untagged_bitmap[k];
    uint32_t untagged_diff = c ^ d;
#endif // 0

    base_bit = k * 32;
    int i = -1;
    int done = 0;
    while (!done) {
      int j = find_next_bit(i, vlan_diff);
      if (j > 0) {
        // vlan added or removed
        int vid = j - 1 + base_bit;
        bool egress_untagged = false;

        // check if egress is untagged
        if (new_br_vlan->untagged_bitmap[k] & 1 << (j - 1)) {
          egress_untagged = true;

#if 0  // untagged change not yet implemented
       // clear untagged_diff bit
          untagged_diff &= ~((uint32_t)1 << (j - 1));
#endif // 0
        }

        if (new_br_vlan->vlan_bitmap[k] & 1 << (j - 1)) {
          // vlan added
          if (lt == LT_VXLAN) {
            // update vxlan domain
            if (!is_vid_set(vid, vxlan_dom_bitmap)) {
              VLOG(1) << __FUNCTION__ << ": new vxlan domain vid=" << vid
                      << ", tunnel_id=" << tunnel_id;

              vxlan_domain.emplace(vid, tunnel_id);
              set_vid(vid, vxlan_dom_bitmap);
            } else {
              // XXX TODO check the map
            }

            // update all bridge ports to be access ports
            update_access_ports(_link, new_link ? new_link : old_link, vid,
                                tunnel_id, bridge_ports, true);
          } else {
            assert(pport_no);
            if (is_vid_set(vid, vxlan_dom_bitmap)) {
              // configure as access port
              std::string port_name = std::string(rtnl_link_get_name(_link));
              auto vxd_it = vxlan_domain.find(vid);

              if (vxd_it != vxlan_domain.end()) {
                vxlan->create_access_port((new_link) ? new_link : old_link,
                                          vxd_it->second, port_name, pport_no,
                                          vid, egress_untagged, nullptr);
              } else {
                LOG(FATAL) << __FUNCTION__
                           << ": should not happen, something is broken";
              }
            } else {
              // normal vlan port
              VLOG(3) << __FUNCTION__ << ": add vid=" << vid
                      << " on pport_no=" << pport_no
                      << " link: " << OBJ_CAST(_link);
              sw->egress_bridge_port_vlan_add(pport_no, vid, egress_untagged);
              sw->ingress_port_vlan_add(pport_no, vid,
                                        new_br_vlan->pvid == vid);
            }
          }
        } else {
          // vlan removed
          if (lt == LT_VXLAN) {
            unset_vid(vid, vxlan_dom_bitmap);
            vxlan_domain.erase(vid);

            // update all bridge ports to be normal bridge ports
            update_access_ports(_link, new_link ? new_link : old_link, vid,
                                tunnel_id, bridge_ports, false);
          } else {
            VLOG(3) << __FUNCTION__ << ": remove vid=" << vid
                    << " on pport_no=" << pport_no
                    << " link: " << OBJ_CAST(_link);
            sw->ingress_port_vlan_remove(pport_no, vid,
                                         old_br_vlan->pvid == vid);

            // delete all FM pointing to this group first
            sw->l2_addr_remove_all_in_vlan(pport_no, vid);

            std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> filter(
                rtnl_neigh_alloc(), rtnl_neigh_put);

            rtnl_neigh_set_ifindex(filter.get(), rtnl_link_get_ifindex(bridge));
            rtnl_neigh_set_master(filter.get(), rtnl_link_get_master(bridge));
            rtnl_neigh_set_family(filter.get(), AF_BRIDGE);
            rtnl_neigh_set_vlan(filter.get(), vid);
            rtnl_neigh_set_flags(filter.get(), NTF_MASTER | NTF_EXT_LEARNED);
            rtnl_neigh_set_state(filter.get(), NUD_REACHABLE);

            nl_cache_foreach_filter(l2_cache.get(), OBJ_CAST(filter.get()),
                                    [](struct nl_object *o, void *arg) {
                                      VLOG(3) << "l2_cache remove object " << o;
                                      nl_cache_remove(o);
                                    },
                                    nullptr);

            sw->egress_bridge_port_vlan_remove(pport_no, vid);
          }
        }

        i = j;
      } else {
        done = 1;
      }
    }

#if 0 // not yet implemented the update
		done = 0;
		i = -1;
		while (!done) {
			// vlan is existing, but swapping egress tagged/untagged
			int j = find_next_bit(i, untagged_diff);
			if (j > 0) {
				// egress untagged changed
				int vid = j - 1 + base_bit;
				bool egress_untagged = false;

				// check if egress is untagged
				if (new_br_vlan->untagged_bitmap[k] & 1 << (j-1)) {
					egress_untagged = true;
				}

				// XXX implement update
				fm_driver.update_port_vid_egress(devname, vid, egress_untagged);


				i = j;
			} else {
				done = 1;
			}
		}
#endif
  }
}