File indexing completed on 2024-04-28 11:21:07

0001 /* markdown: a C implementation of John Gruber's Markdown markup language.
0002  *
0003  * Copyright (C) 2007 David L Parsons.
0004  * The redistribution terms are provided in the COPYRIGHT file that must
0005  * be distributed with this source code.
0006  */
0007 #include <stdio.h>
0008 #include "markdown.h"
0009 #include "cstring.h"
0010 #include "amalloc.h"
0011 
0012 struct frame {
0013     int indent;
0014     char c;
0015 };
0016 
0017 typedef STRING(struct frame) Stack;
0018 
0019 static char *
0020 Pptype(int typ)
0021 {
0022     switch (typ) {
0023     case WHITESPACE: return "whitespace";
0024     case CODE      : return "code";
0025     case QUOTE     : return "quote";
0026     case MARKUP    : return "markup";
0027     case HTML      : return "html";
0028     case DL        : return "dl";
0029     case UL        : return "ul";
0030     case OL        : return "ol";
0031     case LISTITEM  : return "item";
0032     case HDR       : return "header";
0033     case HR        : return "hr";
0034     case TABLE     : return "table";
0035     case SOURCE    : return "source";
0036     case STYLE     : return "style";
0037     default        : return "mystery node!";
0038     }
0039 }
0040 
0041 static void
0042 pushpfx(int indent, char c, Stack *sp)
0043 {
0044     struct frame *q = &EXPAND(*sp);
0045 
0046     q->indent = indent;
0047     q->c = c;
0048 }
0049 
0050 
0051 static void
0052 poppfx(Stack *sp)
0053 {
0054     S(*sp)--;
0055 }
0056 
0057 
0058 static void
0059 changepfx(Stack *sp, char c)
0060 {
0061     char ch;
0062 
0063     if ( !S(*sp) ) return;
0064 
0065     ch = T(*sp)[S(*sp)-1].c;
0066 
0067     if ( ch == '+' || ch == '|' )
0068     T(*sp)[S(*sp)-1].c = c;
0069 }
0070 
0071 
0072 static void
0073 printpfx(Stack *sp, FILE *f)
0074 {
0075     int i;
0076     char c;
0077 
0078     if ( !S(*sp) ) return;
0079 
0080     c = T(*sp)[S(*sp)-1].c;
0081 
0082     if ( c == '+' || c == '-' ) {
0083     fprintf(f, "--%c", c);
0084     T(*sp)[S(*sp)-1].c = (c == '-') ? ' ' : '|';
0085     }
0086     else
0087     for ( i=0; i < S(*sp); i++ ) {
0088         if ( i )
0089         fprintf(f, "  ");
0090         fprintf(f, "%*s%c", T(*sp)[i].indent + 2, " ", T(*sp)[i].c);
0091         if ( T(*sp)[i].c == '`' )
0092         T(*sp)[i].c = ' ';
0093     }
0094     fprintf(f, "--");
0095 }
0096 
0097 
0098 static void
0099 dumptree(Paragraph *pp, Stack *sp, FILE *f)
0100 {
0101     int count;
0102     Line *p;
0103     int d;
0104     static char *Begin[] = { 0, "P", "center" };
0105 
0106     while ( pp ) {
0107     if ( !pp->next )
0108         changepfx(sp, '`');
0109     printpfx(sp, f);
0110 
0111     if ( pp->typ == HDR )
0112         d += fprintf(f, "[h%d", pp->hnumber);
0113     else
0114         d = fprintf(f, "[%s", Pptype(pp->typ));
0115     if ( pp->ident )
0116         d += fprintf(f, " %s", pp->ident);
0117 
0118 #ifdef GITHUB_CHECKBOX
0119     if ( pp->flags )
0120         d += fprintf(f, " %x", pp->flags);
0121 #endif
0122         
0123     if ( pp->align > 1 )
0124         d += fprintf(f, ", <%s>", Begin[pp->align]);
0125 
0126     for (count=0, p=pp->text; p; ++count, (p = p->next) )
0127         ;
0128 
0129     if ( count )
0130         d += fprintf(f, ", %d line%s", count, (count==1)?"":"s");
0131 
0132     d += fprintf(f, "]");
0133 
0134     if ( pp->down ) {
0135         pushpfx(d, pp->down->next ? '+' : '-', sp);
0136         dumptree(pp->down, sp, f);
0137         poppfx(sp);
0138     }
0139     else fputc('\n', f);
0140     pp = pp->next;
0141     }
0142 }
0143 
0144 
0145 int
0146 mkd_dump(Document *doc, FILE *out, mkd_flag_t flags, char *title)
0147 {
0148     Stack stack;
0149 
0150     if (mkd_compile(doc, flags) ) {
0151 
0152     CREATE(stack);
0153     pushpfx(fprintf(out, "%s", title), doc->code->next ? '+' : '-', &stack);
0154     dumptree(doc->code, &stack, out);
0155     DELETE(stack);
0156 
0157     return 0;
0158     }
0159     return -1;
0160 }