Trabalho Prático 2
Processamento de Linguagens
commands.c
Ir para a documentação deste ficheiro.
1 /**
2  * @file commands.c
3  * @author
4  * - José Moura <a13742|at|alunos.ipca.pt>
5  * - Óscar Silva <a14383|at|alunos.ipca.pt>
6  * - Daniel Filipe <a17442|at|alunos.ipca.pt>
7  * @date 01 Jan 2020
8  * @brief
9  * Este ficheiro contem as instruções necessárias para executar os comandos vindos do grammar.y
10  */
11 
12 #include <math.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <time.h>
17 #include "../src/commands.h"
18 #include "../src/imageraster.h"
19 #include "../include/grammar.tab.h"
20 
21 /**
22  * @brief
23  * Recebe 3 valores e cria uma estrutura de cor
24  * @param r valor da cor red
25  * @param g valor da cor gree
26  * @param b valor da cor blue
27  * @return
28  */
29 Colour *parseColour(Value *r, Value *g, Value *b) {
30  Colour* v = (Colour*)malloc(sizeof(Colour));
31  v->r = *r;
32  v->g = *g;
33  v->b = *b;
34  return v;
35 }
36 
37 /**
38  * @brief
39  * Recebe 2 valores e devolve uma estrutura do tipo dimension (x x y)
40  * @param x valor de x
41  * @param y valor de y
42  * @return
43  */
44 Dimension *parseDimension(Value *x, Value *y) {
45  Dimension* v = (Dimension*)malloc(sizeof(Dimension));
46  v->x = *x;
47  v->y = *y;
48  return v;
49 }
50 
51 /**
52  * @brief
53  * Recebe 2 valores de x e y e uma lista de pontos
54  * @param lst lista de pontos
55  * @param x valor do ponto em x a adicionar à lista
56  * @param y valor do ponto em y a adicionar à lista
57  * @return
58  */
59 Point *parsePoint(Point *lst, Value *x, Value *y) {
60  Point* v = (Point*)malloc(sizeof(Point));
61  v->x = *x;
62  v->y = *y;
63  v->next = lst;
64  return v;
65 }
66 
67 /**
68  * @brief
69  * Cria uma estutura do tipo value dependendo se enviamos uma string ou um valor
70  * @param val valor inteiro
71  * @param str valor string
72  * @return
73  */
74 Value *parseValue(int val, char* str) {
75  Value* v = (Value*)malloc(sizeof(Value));
76  v->val = val;
77  v->var = str; // so we know this is an INTeger
78  return v;
79 }
80 
81 /**
82  * @brief
83  * Função que cria um comando e o devolve
84  * @param command Inteiro que identifica o comando
85  * @param pt Pontos (1,2 3,4 5,6)
86  * @param dim Dimensoes (20x10)
87  * @param col Cor (r:g:b)
88  * @param val Um valor (Usado para variaveis ou valores inteiros)
89  * @param val2 Um outro Valor (Usado para variaveis ou valores inteiros)
90  * @param str Um valor string (Usado para comandos que necessitem de strings tipo LOAD e SAVE)
91  * @param str2
92  * @param child Commandos encadeados neste
93  * @return
94  */
95 Command* newCommand(int command,Point *pt,Dimension *dim,Colour *col,Value *val,Value *val2 ,Value *str,Value *str2,Command *child)
96 {
97  Command *node = (Command*) malloc (sizeof(Command));
98  node->command = command;
99  node->point = pt;
100  node->dimension = dim;
101  node->color = col;
102  node->val = val;
103  node->val2 = val2;
104  node->str = str;
105  node->str2 = str2;
106  node->child = child;
107  node->next = NULL;
108  return node;
109 }
110 
111 /**
112  * @brief
113  * Recebe uma lista de comandos e um comando e insere o mesmo na lista
114  * @param lst Lista de Comandos
115  * @param cmd Nodo
116  * @return
117  */
118 Command* insertCommand(Command *lst, Command *cmd) {
119  cmd->next = lst;
120  return cmd;
121 }
122 
123 /**
124  * @brief
125  * Altera o valor de uma variavel
126  * @param lst lista de variaveis
127  * @param varName nome da variavel
128  * @param varValue novo valor inteiro
129  * @return
130  */
131 VarList* updateVar(VarList *lst, char *varName, int varValue) {
132  if (lst == NULL) {
133  lst = (VarList*) malloc(sizeof(VarList));
134  lst->next = NULL;
135  lst->var = strdup(varName);
136  lst->val = varValue;
137  }
138  else {
139  if (strcmp(lst->var, varName) == 0) {
140  lst->val = varValue;
141  }
142  else {
143  lst->next = updateVar(lst->next, varName, varValue);
144  }
145  }
146  return lst;
147 }
148 
149 /**
150  * @brief
151  * Devolve o valor de uma variavel através do nome da mesma
152  * @param lst Lista de Variaveis
153  * @param varName Nome da Variavel
154  * @return Inteiro do valor da variavel
155  */
156 int evalVar(VarList *lst, char *varName) {
157  if (lst == NULL) {
158  fprintf(stderr, "Variable %s is undefined\n", varName);
159  exit(1);
160  }
161  if (strcmp(lst->var, varName) == 0) {
162  return lst->val;
163  } else {
164  return evalVar(lst->next, varName);
165  }
166 }
167 
168 /**
169  * Devolve o valor de uma variavel através da estrutura de uma variavel
170  * @param lst Lista de Variaveis
171  * @param val Valor Struct
172  * @return
173  */
174 int evalValue(VarList *lst, Value *val) {
175 
176  if (val->var == NULL) {
177  return val->val;
178  }
179  else {
180  return evalVar(lst, val->var);
181  }
182 }
183 
184 /**
185  * @brief
186  * Cria uma nova estrutura que irá servir para correr os comandos
187  * @return Estrutura com uma imagem
188  * @see Image
189  */
190 Image *newImage() {
191  Image *image = (Image*) malloc(sizeof(Image));
192  image->r = 0;
193  image->g = 0;
194  image->b = 0;
195  image->x_size = 1;
196  image->y_size = 1;
197  image->vars = NULL; // No variables defined so far...
198  return image;
199 }
200 
201 /**
202  * @brief
203  * Função chamada no final de fazer parsing à gramatica
204  * program : instructionList { Run($1); }
205  * A mesma cria uma imagem e corre os comandos contidos na lst
206  * @param lst Lista de Comandos a Correr
207  */
208 void Run(Command *lst) {
209  Image *image = newImage();
210  runCommands(lst, image);
211 }
212 
213 /**
214  * @brief
215  * Função recursiva principal que corre os comandos pertencentes à lista de comandos que foi feito o parsing
216  * @param lst Lista de comandos
217  * @param image Estrutura com informação da imagem
218  */
219 void runCommands(Command *lst, Image *image) {
220 
221  if (!lst) return;
222  switch(lst->command) {
223  case FOR:
224  {
225  // @done
226  int from = evalValue(image->vars, lst->val);
227  int to = evalValue(image->vars, lst->val2);
228  for (int var=from; var<=to ;var++) {
229  image->vars = updateVar(image->vars, lst->str->var, var);
230  runCommands(lst->child , image);
231  }
232  }
233  break;
234  case NEW:
235  {
236  // @done
237  image->x_size = evalValue(image->vars, &lst->dimension->x);
238  image->y_size = evalValue(image->vars, &lst->dimension->y);
239 
240  if(image->x_size<=0 || image->y_size<=0) {
241  fprintf(stderr, "X_SIZE or Y_SIZE incorrect value\n");
242  exit(1);
243  }
244 
245  // get rgb background value, default 0,0,0
246  int r = (lst->color == NULL) ? 255 : evalValue(image->vars, &lst->color->r);
247  int g = (lst->color == NULL) ? 255 : evalValue(image->vars, &lst->color->g);
248  int b = (lst->color == NULL) ? 255 : evalValue(image->vars, &lst->color->b);
249 
250  // rgb cannot be bigger than 255
251  r = (r>255) ? 255 : r;
252  g = (g>255) ? 255 : g;
253  b = (b>255) ? 255 : b;
254 
255  image->img_data = malloc((3 * image->x_size * image->y_size) * sizeof(int));
256 
257  // fill image with background color
258  imageFill(image->img_data,image->x_size,image->y_size,r,g,b);
259  // fprintf(stderr,"\nNEW =>\n");
260  }
261  break;
262  case COLOR:
263  {
264  // @done
265  // get rgb colour value, default 0,0,0
266  image->r = evalValue(image->vars, &lst->color->r);
267  image->g = evalValue(image->vars, &lst->color->g);
268  image->b = evalValue(image->vars, &lst->color->b);
269 
270  // rgb cannot be bigger than 255
271  image->r = (image->r > 255) ? 255 : image->r;
272  image->g = (image->g > 255) ? 255 : image->g;
273  image->b = (image->b > 255) ? 255 : image->b;
274 
275  //printf("COLOR CHANGE - %d\\%d\\%d =>\n", def_r,def_g,def_b);
276  }
277  break;
278  case LOAD:
279  {
280  // @done
281  FILE *fp = fopen(lst->str->var, "r");
282 
283  fprintf(stderr,"\nReaded File %s", lst->str->var);
284 
285  readImageHeader(fp,&image->x_size,&image->y_size);
286 
287  image->img_data = malloc((3 * image->x_size * image->y_size) * sizeof(int));
288 
289  readImage(fp,image->img_data);
290 
291  fprintf(stderr,"[OK]\n");
292  }
293  break;
294  case SAVE:
295  {
296  // @done
297  FILE *fp = fopen(lst->str->var, "w");
298 
299  fprintf(stderr,"\nSaved File %s", lst->str->var);
300 
301  // Save image to file
302  writeImage(fp,image->img_data,lst->str->var, image->x_size,image->y_size);
303  fprintf(stderr,"[OK]\n");
304  }
305  break;
306  case POINT:
307  {
308  // @done
309 
310  // get rgb colour value, default def_r,def_g,def_b
311  int r = (lst->color == NULL) ? image->r : evalValue(image->vars, &lst->color->r);
312  int g = (lst->color == NULL) ? image->g : evalValue(image->vars, &lst->color->g);
313  int b = (lst->color == NULL) ? image->b : evalValue(image->vars, &lst->color->b);
314 
315  int x = (lst->point == NULL) ? 1 : evalValue(image->vars, &lst->point->x);
316  int y = (lst->point == NULL) ? 1 : evalValue(image->vars, &lst->point->y);
317 
318  drawPoint(image->img_data,image->x_size,image->y_size,x,y,r,g,b);
319 
320  }
321  break;
322  case LINE:
323  {
324  // @done
325  // get rgb colour value, default def_r,def_g,def_b
326  int r = (lst->color == NULL) ? image->r : evalValue(image->vars, &lst->color->r);
327  int g = (lst->color == NULL) ? image->g : evalValue(image->vars, &lst->color->g);
328  int b = (lst->color == NULL) ? image->b : evalValue(image->vars, &lst->color->b);
329 
330  int x1 = (lst->point == NULL) ? 1 : evalValue(image->vars, &lst->point->x);
331  int y1 = (lst->point == NULL) ? 1 : evalValue(image->vars, &lst->point->y);
332 
333  int x2 = (lst->point->next == NULL) ? 1 : evalValue(image->vars, &lst->point->next->x);
334  int y2 = (lst->point->next == NULL) ? 1 : evalValue(image->vars, &lst->point->next->y);
335 
336 
337  drawLine(image->img_data,image->x_size,image->y_size,x1,y1,x2,y2,r,g,b);
338 
339  }
340  break;
341  case RECT:
342  {
343  // @done
344  // get rgb colour value, default def_r,def_g,def_b
345 
346  int r = (lst->color == NULL) ? image->r : evalValue(image->vars, &lst->color->r);
347  int g = (lst->color == NULL) ? image->g : evalValue(image->vars, &lst->color->g);
348  int b = (lst->color == NULL) ? image->b : evalValue(image->vars, &lst->color->b);
349 
350 
351  int x1 = evalValue(image->vars, &lst->point->x);
352  int y1 = evalValue(image->vars, &lst->point->y);
353 
354  int x2 = (lst->dimension == NULL) ?
355  evalValue(image->vars, &lst->point->next->x)
356  : x1 + evalValue(image->vars, &lst->dimension->x) - 1
357  ;
358  int y2 = (lst->dimension == NULL) ?
359  evalValue(image->vars, &lst->point->next->y)
360  : y1 + evalValue(image->vars, &lst->dimension->y) - 1
361  ;
362  //printf("%d %d %d %d %d %d %d xysize %d %d----",x1,y1,x2,y2,r,g,b,image->x_size,image->y_size);
363  //exit(1);
364  // Parte superior
365  drawLine(image->img_data,image->x_size,image->y_size,x2,y1,x1,y1,r,g,b);
366 
367  // Lateral direita
368  drawLine(image->img_data,image->x_size,image->y_size,x2,y2,x2,y1,r,g,b);
369 
370  // Baixo
371  drawLine(image->img_data,image->x_size,image->y_size,x2,y2,x1,y2,r,g,b);
372 
373  // Lateral Equerda
374  drawLine(image->img_data,image->x_size,image->y_size,x1,y2,x1,y1,r,g,b);
375 
376  }
377  break;
378  case RECTFILL:
379  {
380  // @done
381  // get rgb colour value, default def_r,def_g,def_b
382  int r = (lst->color == NULL) ? image->r : evalValue(image->vars, &lst->color->r);
383  int g = (lst->color == NULL) ? image->g : evalValue(image->vars, &lst->color->g);
384  int b = (lst->color == NULL) ? image->b : evalValue(image->vars, &lst->color->b);
385 
386  int x1 = evalValue(image->vars, &lst->point->x);
387  int y1 = evalValue(image->vars, &lst->point->y);
388 
389  int x2 = (lst->dimension == NULL) ?
390  evalValue(image->vars, &lst->point->next->x)
391  : x1 + evalValue(image->vars, &lst->dimension->x) -1
392  ;
393  int y2 = (lst->dimension == NULL) ?
394  evalValue(image->vars, &lst->point->next->y)
395  : y1 + evalValue(image->vars, &lst->dimension->y)-1
396  ;
397 
398  for (int i=y1; i<= y2; i++) {
399  // Parte superior
400  drawLine(image->img_data,image->x_size,image->y_size,x1,i,x2,i,r,g,b);
401  }
402  }
403  break;
404  case POLYLINE:
405  {
406  // @done
407 
408  // get rgb colour value, default def_r,def_g,def_b
409  int r = (lst->color == NULL) ? image->r : evalValue(image->vars, &lst->color->r);
410  int g = (lst->color == NULL) ? image->g : evalValue(image->vars, &lst->color->g);
411  int b = (lst->color == NULL) ? image->b : evalValue(image->vars, &lst->color->b);
412 
413  while (lst->point->next != NULL) {
414  int x1 = (lst->point == NULL) ? 1 : evalValue(image->vars, &lst->point->x);
415  int y1 = (lst->point == NULL) ? 1 : evalValue(image->vars, &lst->point->y);
416 
417  int x2 = (lst->point->next == NULL) ? 1 : evalValue(image->vars, &lst->point->next->x);
418  int y2 = (lst->point->next == NULL) ? 1 : evalValue(image->vars, &lst->point->next->y);
419 
420  drawLine(image->img_data,image->x_size,image->y_size,x1,y1,x2,y2,r,g,b);
421 
422  //printf("LINE %d,%d %d,%d;\n",x1,y1,x2,y2);
423  //iterate
424  lst->point = lst->point->next;
425  }
426  }
427  break;
428  case CIRC:
429  {
430  // @done
431  // get rgb colour value, default def_r,def_g,def_b
432  int r = (lst->color == NULL) ? image->r : evalValue(image->vars, &lst->color->r);
433  int g = (lst->color == NULL) ? image->g : evalValue(image->vars, &lst->color->g);
434  int b = (lst->color == NULL) ? image->b : evalValue(image->vars, &lst->color->b);
435 
436  int x = (lst->point == NULL) ? 1 : evalValue(image->vars, &lst->point->x);
437  int y = (lst->point == NULL) ? 1 : evalValue(image->vars, &lst->point->y);
438 
439  int raio = (lst->val == NULL) ? 1 : evalValue(image->vars, lst->val);
440 
441  drawCircle(image->img_data,image->x_size,image->y_size, raio,x,y,r,g,b);
442 
443  };
444  break;
445 
446  case INVERT:
447  {
448  for (int i = 0; i< (image->x_size*image->y_size * 3); i++) {
449  image->img_data[i] = 255 - image->img_data[i];
450  }
451 
452 
453  };
454  break;
455 
456 
457  case CIRCFILL:
458  {
459  // @done
460  // get rgb colour value, default def_r,def_g,def_b
461  int r = (lst->color == NULL) ? image->r : evalValue(image->vars, &lst->color->r);
462  int g = (lst->color == NULL) ? image->g : evalValue(image->vars, &lst->color->g);
463  int b = (lst->color == NULL) ? image->b : evalValue(image->vars, &lst->color->b);
464 
465  int x = (lst->point == NULL) ? 1 : evalValue(image->vars, &lst->point->x);
466  int y = (lst->point == NULL) ? 1 : evalValue(image->vars, &lst->point->y);
467 
468  int raio = (lst->val == NULL) ? 1 : evalValue(image->vars, lst->val);
469 
470  for (int i=raio; i>0 ; i--) {
471  drawCircle(image->img_data,image->x_size,image->y_size, i,x,y,r,g,b);
472  }
473 
474 
475  };
476  break;
477  case ATTRIB:
478  {
479  // @done
480  // get value of variable or value
481  int value = evalValue(image->vars, lst->val);
482  // update variable
483  image->vars = updateVar(image->vars, lst->str->var, value);
484  }
485  break;
486  case ATTRIB_RAND:
487  {
488  // @done
489  int value = evalValue(image->vars, lst->val);
490  image->vars = updateVar(image->vars, lst->str->var, gera_random(0,value));
491  //printf("\n%s = %d . %d\n", lst->str->var, evalValue(image->vars, lst->str), gera_random(0,value));
492  }
493  break;
494  }
495  runCommands(lst->next, image);
496 }
497 
498 /**
499  * @brief
500  * Gera um numero random entre min e max
501  * @param min
502  * @param max
503  * @return
504  */
505 int gera_random(int min, int max) {
506 
507  return rand() % max + min;
508 }
_Image::b
int b
Definition: commands.h:86
_Command::val
Value * val
Definition: commands.h:73
_Image::vars
VarList * vars
Definition: commands.h:88
_varList::var
char * var
Definition: commands.h:21
gera_random
int gera_random(int min, int max)
Gera um numero random entre min e max.
Definition: commands.c:505
_Command::command
int command
Definition: commands.h:69
_Image::r
int r
Definition: commands.h:86
_Image::x_size
int x_size
Definition: commands.h:87
parseColour
Colour * parseColour(Value *r, Value *g, Value *b)
Recebe 3 valores e cria uma estrutura de cor.
Definition: commands.c:29
insertCommand
Command * insertCommand(Command *lst, Command *cmd)
Recebe uma lista de comandos e um comando e insere o mesmo na lista.
Definition: commands.c:118
newCommand
Command * newCommand(int command, Point *pt, Dimension *dim, Colour *col, Value *val, Value *val2, Value *str, Value *str2, Command *child)
Função que cria um comando e o devolve.
Definition: commands.c:95
_Colour::g
Value g
Definition: commands.h:60
Run
void Run(Command *lst)
Função chamada no final de fazer parsing à gramatica program : instructionList { Run($1); } A mesma c...
Definition: commands.c:208
_varList::val
float val
Definition: commands.h:22
_Point::y
Value y
Definition: commands.h:50
_Command::point
Point * point
Definition: commands.h:70
_Command::val2
Value * val2
Definition: commands.h:74
_Command::child
struct _Command * child
Definition: commands.h:78
parseDimension
Dimension * parseDimension(Value *x, Value *y)
Recebe 2 valores e devolve uma estrutura do tipo dimension (x x y)
Definition: commands.c:44
_Dimension::y
Value y
Definition: commands.h:41
_Command::dimension
Dimension * dimension
Definition: commands.h:71
_Value::val
int val
Definition: commands.h:32
_Colour::b
Value b
Definition: commands.h:61
_Command::str
Value * str
Definition: commands.h:75
_Command::str2
Value * str2
Definition: commands.h:76
_Point::x
Value x
Definition: commands.h:49
_Command::color
Colour * color
Definition: commands.h:72
_varList::next
struct _varList * next
Definition: commands.h:23
_Point::next
struct _Point * next
Definition: commands.h:51
runCommands
void runCommands(Command *lst, Image *image)
Função recursiva principal que corre os comandos pertencentes à lista de comandos que foi feito o par...
Definition: commands.c:219
newImage
Image * newImage()
Cria uma nova estrutura que irá servir para correr os comandos.
Definition: commands.c:190
parsePoint
Point * parsePoint(Point *lst, Value *x, Value *y)
Recebe 2 valores de x e y e uma lista de pontos.
Definition: commands.c:59
_Dimension::x
Value x
Definition: commands.h:40
_Image::y_size
int y_size
Definition: commands.h:87
updateVar
VarList * updateVar(VarList *lst, char *varName, int varValue)
Altera o valor de uma variavel.
Definition: commands.c:131
_Colour::r
Value r
Definition: commands.h:59
_Command::next
struct _Command * next
Definition: commands.h:77
parseValue
Value * parseValue(int val, char *str)
Cria uma estutura do tipo value dependendo se enviamos uma string ou um valor.
Definition: commands.c:74
evalVar
int evalVar(VarList *lst, char *varName)
Devolve o valor de uma variavel através do nome da mesma.
Definition: commands.c:156
_Value::var
char * var
Definition: commands.h:31
_Image::g
int g
Definition: commands.h:86
evalValue
int evalValue(VarList *lst, Value *val)
Definition: commands.c:174