aboutsummaryrefslogtreecommitdiff
path: root/Converter/src/compiler.c
blob: 9da3667b3f59db99ab896ea80d00d75be895c4ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include "../includes/compiler.h"
#include <stdio.h>
#include <string.h>

int find_string(string src, string query, size_t sz_src, size_t sz_query)
{
  int j = 0;
  while ((j < (sz_src - sz_query)) && (strncmp(query, src + j, sz_query))) ++j;
  return j;
}

bool is_token(char c)
{
  bool token_check = false;
  for (int i = 0; i < N_TOKENS; ++i)
    if (c == TOKENS[i])
    {
      token_check = true;
      break;
    }
  return token_check;
}

void compile_inner_text(string dest, string src, size_t sz_src,
                        string line_or_source)
{
  /* cursor is the current index on the dest pointer
   * lower represents the last tag character before content
   * upper represents the first tag character after content
   *
   * size_of_content is self explanatory (size of content delimited by tags)
   * tag_size is the compiled size of a tag
   * md_tag_size is the precompiled size of a tag
   *
   * tag is the string for the open HTML tag
   * close_tag is the string for the close HTML tag
   *
   * i and j are iterator variables
   */
  int cursor, lower, upper;
  size_t size_of_content, tag_size, md_tag_size;
  string tag, close_tag;
  int i, j;

  lower = 0;
  upper = 0;
  cursor = 0;

  for (i = 0; i < size_of_line; ++i)
  {
    // Asterisk routine
    if (src[i] == '*')
    {
      j = i + 1;

      // Twin asterisks
      if (src[i + 1] == '*')
      {
        tag = "<strong>";
        close_tag = "</strong>";
        tag_size = 8;
        md_tag_size = 2;

        // Make j the cursor seeking for the matching asterisk pair
        while ((j < size_of_line - 1) && (src[j] != '*' || src[j + 1] != '*'))
          ++j;

        // if found
        if (src[j] == '*')
        {
          lower = i + 1;
          upper = j;
        }
        else
        {
          // ERROR
          fprintf(stderr, "No matching asterisk for %s:%d\n", line_or_source,
                  i);
          exit(-1);
        }
      }

      // one asterisk
      else
      {
        tag = "<i>";
        close_tag = "</i>";
        tag_size = 3;
        md_tag_size = 1;
        while ((j < size_of_line) && (src[j] != '*')) ++j;

        if (src[j] == '*')
        {
          lower = i;
          upper = j;
        }
        else
        {
          // error, no matching asterisk
          fprintf(stderr, "No matching asterisk for %s:%d\n", line_or_source,
                  i);
          exit(-1);
        }
      }

      /*
       * Copy all
       */
      size_of_content = upper - lower - 1;
      strncpy(dest + cursor, tag, tag_size);
      strncpy(dest + cursor + tag_size, src + lower + 1, size_of_content);
      strncpy(dest + cursor + tag_size + size_of_content, close_tag,
              tag_size + 1);
      cursor +=
          tag_size + size_of_content + tag_size + 1; // shift after operation
      i += size_of_content + (2 * md_tag_size) - 1;
    }
    else
    {
      strncpy(dest + cursor, &src[i], 1);
      cursor += 1;
    }
  }
}

string compile_line(string line, size_t size_of_line, string line_or_source)
{
  string compiled_line;
  size_t size_of_content;

  if (line[0] == '#') // Compile a header
  {
    // Get the level of header (h1, h2, etc)
    int depth;
    for (depth = 1; line[depth] == '#'; ++depth) continue;
    size_of_content = size_of_line - depth; // remove hashes

    // Generate the header tags based on depth
    const int tag_size = 4;
    const int close_tag_size = 5;
    string tag = malloc(sizeof(*tag) * 5);
    string close_tag = malloc(sizeof(*close_tag) * 6);
    sprintf(tag, "<h%d>", depth);
    sprintf(close_tag, "</h%d>", depth);

    // allocate buffer with extra 9 characters for the tags
    compiled_line = malloc(sizeof(*compiled_line) *
                           (size_of_line + tag_size + close_tag_size + 1));
    // write h1 to start of compiled_line
    strncpy(compiled_line, tag, tag_size);
    // write the rest of the line to the compiled_line
    strncpy(compiled_line + tag_size, line + depth, size_of_line);
    // write the end tags
    strncpy(compiled_line + size_of_content + tag_size, close_tag,
            close_tag_size);
    compiled_line[size_of_content + tag_size + close_tag_size] = '\0';
  }
  else if (line[0] == '-') // Compile a list item
  {
    string tag = "<li>";
    string close_tag = "</li>";
    size_of_content = size_of_line - 1;

    compiled_line = malloc(sizeof(*compiled_line) * (size_of_content + 10));
    strncpy(compiled_line, tag, 4);
    strncpy(compiled_line + 4, line + 1, size_of_line);
    strncpy(compiled_line + size_of_content + 4, close_tag, 5);
    compiled_line[size_of_content + 9] = '\0'; // terminate string
  }
  else // Compile a standard piece of text
  {
    compiled_line = malloc(sizeof(*compiled_line) * size_of_line * 2);
    compile_inner_text(compiled_line, line, size_of_line, line_or_source);
  }

  return compiled_line;
}