-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathInforme TP1 Duarte Fernandez Landino.tex
1226 lines (1020 loc) · 41.5 KB
/
Informe TP1 Duarte Fernandez Landino.tex
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\documentclass[a4paper,10pt]{article}
\usepackage{graphicx}
\usepackage[ansinew]{inputenc}
\usepackage[spanish]{babel}
\usepackage{listings}
\usepackage{float}
\usepackage[justification=centering]{caption}
\usepackage[T1]{fontenc}
\title{ \textbf{Trabajo práctico \#1: conjunto de instrucciones MIPS}}
\author{ Santiago Fernandez, \textit{Padrón Nro. 94.489} \\
\texttt{ fernandezsantid@gmail.com } \\[2.5ex]
Francisco Landino, \textit{Padrón Nro. 94.475} \\
\texttt{ landinofrancisco@gmail.com } \\[2.5ex]
Matias Duarte, \textit{Padrón Nro. 92.186} \\
\texttt{ duarte.mati@gmail.com } \\[2.5ex]
\normalsize{2do. Cuatrimestre de 2014} \\
\normalsize{66.20 Organización de Computadoras $-$ Práctica Jueves} \\
\normalsize{Facultad de Ingeniería, Universidad de Buenos Aires} \\
}
\date{}
\begin{document}
\maketitle
\thispagestyle{empty} % quita el número en la primer página
\begin{abstract}
Este trabajo práctico trata de una versión en lenguaje C, de un programa que lee desde un archivo de texto o desde STDIN, un texto que contiene tags, posiblemente anidados, y verifica que la estructura sea correcta. Además, se hizo un version en Assembly, de una función, para familiarizarse con el conjunto de instrucciones MIPS32 y el concepto de ABI.
\end{abstract}
\pagebreak
\tableofcontents
\pagebreak
\section{Introducción}
\par Como objetivo de este trabajo practico se trabajo tanto usando el conjunto de instrucciones de MIPS32 como en el lenguaje C, para codificar un programa que recibe desde STDIN o desde un archivo de texto, un texto en el cual se encuentran tags, de la forma \emph{<Tag>... </Tag>}, posiblemente anidados. El programa se encarga de verificar que estén correctamente relacionados, lo que significa que el texto que abre un tag sea igual al texto que lo cierra y que estén correctamente anidados.
\par También se trabajo usando el ABI presentado por la cátedra, para guardar los argumentos en el stack entre las llamadas de función a función.
\section{Desarrollo}
\par Para desarrollar este trabajo primero se realizo un programa en lenguaje C, el cual contempla las siguientes condiciones.\\
\par Los \emph{tags} tienen que cumplir con la siguiente estructura:
\begin{itemize}
\item Todos los \emph{tags} abiertos se cierran,
\item Todos los \emph{tags} que se cierran fueron abiertos.
\item Todos los \emph{tags} abiertos dentro de otro \emph{tag} se cierran antes que ?este.
\item Si se detecta una violación de alguna de las reglas anteriores, se especifica el error (\emph{tag} sin cerrar, \emph{tag} sin abrir, \emph{tag} mal anidado) y el numero de línea (empezando por 0) por \textbf{stderr}. En caso de que la estructura del archivo sea valida, el programa debe devolver 0, caso contrario devolver 1, ademas de la salida por \textbf{stderr}.
\end{itemize}
Un \emph{tag} esta compuesto por una secuencia de apertura, de la forma\\ "\textbf{<nombre-tag>}", un contenido que puede ser texto u otros \emph{tags}, y una secuencia de cierre de la forma "\textbf{</nombre-tag>}".
\par Se considera que no pueden haber caracteres del tipo \emph{'<'} o \emph{'>'} sin que implique una apertura o cierre de un \emph{tag}.\\
\par Luego a partir de esta implementacion en C, se desarrollaron las funciones \emph{validate} y \emph{analizarTag} en Assembly MIPS32. Para dicha implementación se uso el ABI que enseño la cátedra durante las clases. Al principio de cada función se crea un stack, donde se guardan los registros del Return Address, Frame Pointer y Global Pointer en las posiciones mas grandes del stack. Luego se guardan los atributos de la función y finalmente los argumentos.
\subsection{Recursos y Portabilidad}
Uno de los objetivos del trabajo práctico es poder probar la portabilidad del
programa en diferentes entornos. En el enunciado se pedía que el programa se pudiera ejecutar en NetBSD[4]/pmax (usando el simulador GXemul[5]) y en la versión
de Linux (Knoppix, RedHat, Debian, Ubuntu) usada para correr el simulador,
Linux/i386. En particular, se lo probó en Ubuntu 14.04. En GXemul se corrió una máquina de arquitectura MIPS cuyo sistema operativo era una versión reciente de NetBSD/pmax. La transferencia de archivos entre la máquina host y la guest se hizo mediante \textit{SSH}. Se procedió de la siguiente manera:
Para trabajar con el GXemul se procedió primero creando una nueva interfaz de red (debe crearse cada vez que se inicia el \textit{host} y con permisos de administrador):
\\
\emph{hostOS\$ sudo ifconfig lo:0 172.20.0.1}
\\
Luego se ejecutó el GXemul en modo X:
\\
\emph{hostOS\$ ./xgxemul -e 3max -d netbsd-pmax.img -x}
\\
Una vez ya ingresado con el usuario y la contraseña en la máquina simulada,
se creó un túnel reverso para saltear las limitaciones propias del GXemul:
\\
\emph{guestOS\$ ssh -R 2222:127.0.0.1:22 usuario@172.20.0.1}
\\
A partir de ese momento y dejando lo anterior en segundo plano, ya se puedo
trabajar mediante SSH de manera más cómoda:
\\
\emph{hostOS\$ ssh -p 2222 root@127.0.0.1}
\\
\subsection{Implementación}
\par El programa en lenguaje C, cuenta con dos archivos: \emph{main.c} y \emph{validate.c}. \\
\par En el archivo \emph{main.c} se encuentran tres funciones:\\
\par \emph{void cargarArchivoAMemoria(FILE* archivoEntrada, char* text)} \\
\par Se encarga de pasar el archivo de entrada a memoria. Por \emph{archivoEntrada} se pasa el puntero al archivo y por \emph{text} se obtiene el puntero a la cadena de texto en memoria.\\
\par \emph{void printManual()} \\
\par Imprime el manual sobre como usar el programa.\\
\par \emph{void checkFile(FILE* file)}\\
\par Verifica si el archivo del cual se quiere levantar es correcto.
\\
\par Luego en el main el programa se encarga de procesar todas las opciones, que se le introducen por argumento, y en el caso de que se pueda levantar el texto correctamente, llama a la función \emph{int validate(char *text, char **errmsg)} la cual se encarga de validar el archivo. Si validate devuelve 0, el programa imprime un 0 y termina su ejecución, pero si validate devuelve un 1, imprime un 1, junto con el mensaje de error en errmsg.\\
\par En el archivo \emph{validate.c} se encuentran dos funciones:\\
\par \emph{int analizarTag(char* text, char* tagEncontrado, int pos, int *contadorLineas)}\\
\par Analiza que el tag que le pasan por argumento sea igual al próximo tag que se cierra. Si encuentra que se abre otro tag antes de encontrar que se cierra un tag, levanta el tag anidado y se llama recursivamente para que lo verifique.
\par \emph{text} es el puntero al texto que se esta analizando.
\par \emph{tagEncontrado} es el puntero a la cadena de texto que contiene el tag que se levanto anteriormente y que hay que comparar con el siguiente tag que se cierre.
\par \emph{pos} es la posición a partir de la cual hay que ir analizando el texto.
\par \emph{contadorLineas} es el puntero al contador que lleva el numero de linea.
\\
\par La función devuelve:
\par \emph{-1} si es un error donde el ultimo tag abierto no fue cerrado.
\par \emph{-2} si es un error donde el tag cerrado no corresponde con el tag abierto.
\par Sino devuelve un numero mayor a cero, el cual indica la posición del texto donde quedo después de analizar que se cerro correctamente el tag.\\\\\\
\par \emph{int validate(char *text, char **errmsg)}\\
\par Va recorriendo el texto hasta que encuentre el fin o hasta que encuentre un tag. Cuando encuentra un tag, lo guarda en el atributo \emph{tagALevantar} y luego llama a la función \emph{analizarTag} para que verifique si se cierra correctamente. Si analizar tag devuelve en un numero mayor a cero, continua analizando el texto desde esa posición, sino verifica que tipo de error es y devuelve por errmsg, el mensaje que se va a imprimir.\\
\par \emph{text} es el puntero al texto a verificar.
\par \emph{errmsg} es el puntero a la cadena de texto donde se tiene que guardar el mensaje de error en el caso de que haya alguno error en la estructura de los tags en el texto.\\
\par La función devuelve un 0 si llego al fin del texto y no se encontró ningún error, con la estructura de los tags, o devuelve un 1 si se encontró algún error.
\subsection{Compilación}
Para compilar el trabajo práctico, realizamos un Makefile para hacer mas sencilla esta tarea.\\
\\
\par Para compilar para C:
\emph{make c}\\
Para compilar para MIPS:
\emph{make mips}\\
Finalmente para limpiar los archivos:
\emph{make clean}\\
\subsection{Corrida de Pruebas}
\par Hicimos corridas con diferentes textos, para probar las diferentes combinaciones posibles y además, probamos el funcionamiento para archivos y para stdin, tanto en su version en c como en mips. Luego, los resultados fueron los siguientes.
\begin{lstlisting}
Corrida de Pruebas en C:
-Prueba Archivos
Para entender estas pruebas, si el programa no devuelve nada es que
termino su ejecucion bien.
En caso contrario devolvia en numero de linea y el mensaje de error.
root@:~/orgaTP1# nl pruebaCorrecta.txt
1 <hola> esto es una prueba </hola>
2 <tag1> prueba </tag1>
root@:~/orgaTP1# ./validate pruebaCorrecta.txt
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# nl pruebaCorrectaAnidados.txt
1 <hola> esto es una prueba </hola>
2 <tag1> prueba </tag1>
3 <hola> <tag2> esto es una prueba con 2 tags </tag2> </hola>
4 <tag5> <tag3> <otroTag> prueba con 3 </otroTag> </tag3> </tag5>
root@:~/orgaTP1# ./validate pruebaCorrectaAnidados.txt
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# nl pruebaIncorrecta.txt
1 <hola> esto es una prueba </hola>
2 <tag1> prueba </chau>
root@:~/orgaTP1# ./validate pruebaIncorrecta.txt
Linea: 2. Tag mal anidado, el ultimo tag cerrado, no corresponde con el
ultimo tag abierto.
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# nl pruebaIncorrectaAnidados.txt
1 <tag1> prueba </tag1>
2 <hola> <tag2> esto es una prueba con 2 tags </tag2> </hola>
3 <tag5> <tag3> <otroTag> prueba con 3 </tag3> </otroTag> </tag5>
root@:~/orgaTP1# ./validate pruebaIncorrectaAnidados.txt
Linea: 3. Tag mal anidado, el ultimo tag cerrado, no corresponde con el
ultimo tag abierto.
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# nl pruebaTagNoCerrado.txt
1 <tag1> prueba </tag1>
2 <hola>
root@:~/orgaTP1# ./validate pruebaTagNoCerrado.txt
Linea: 2. El tag abierto, no fue cerrado.
root@:~/orgaTP1#
---------------------------------------------------------------------------
-Prueba de STDIN
root@:~/orgaTP1# echo "<hola>" | ./validate -i -
Linea: 1. El tag abierto, no fue cerrado.
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# echo "<hola> </hola>" | ./validate -i -
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# ./validate -i -
<hola> <tag2> esto es una prueba de anidados </tag2></hola>
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# ./validate -i -
<hola> <tag2> esto es una prueba erronea de anidados </hola> <tag3>
Linea: 1. Tag mal anidado, el ultimo tag cerrado, no corresponde con
el ultimo tag abierto.
root@:~/orgaTP1#
---------------------------------------------------------------------------
Corrida de Pruebas en MIPS
-Prueba Archivos
Para entender estas pruebas, si el programa no devuelve nada es que
termino su ejecucion bien.
En casa contrario devolvia en numero de linea y el mensaje de error.
root@:~/orgaTP1# nl pruebaCorrectaMips.txt
1 <tag1> prueba </tag1>
2 <hola> esto es una prueba </hola>
root@:~/orgaTP1# ./validate pruebaCorrecta.txt
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# nl pruebaCorrectaAnidadosMips.txt
1 <hola> esto es una prueba </hola>
2 <hola> <tag2> esto es una prueba con 2 tags </tag2> </hola>
3 <tag1> prueba </tag1>
4 <tag5> <tag3> <otroTag> prueba con 3 </otroTag> </tag3> </tag5>
root@:~/orgaTP1# ./validate pruebaCorrectaAnidados.txt
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# nl pruebaIncorrectaMips.txt
1 <hola> esto es una prueba </hola>
2 <tag1> prueba </chau>
root@:~/orgaTP1# ./validate pruebaIncorrecta.txt
Linea: 2. Tag mal anidado, el ultimo tag cerrado, no corresponde con el
ultimo tag abierto.
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# nl pruebaIncorrectaAnidadosMips.txt
1 <tag1> prueba </tag1>
2 <tag5> <tag3> <otroTag> prueba con 3 </tag3> </otroTag> </tag5>
3 <hola> <tag2> esto es una prueba con 2 tags </tag2> </hola>
root@:~/orgaTP1# ./validate pruebaIncorrectaAnidados.txt
Linea: 2. Tag mal anidado, el ultimo tag cerrado, no corresponde con el
ultimo tag abierto.
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# nl pruebaTagNoCerradoMips.txt
1 <hola>
2 <tag1> prueba </tag1>
root@:~/orgaTP1# ./validate pruebaTagNoCerrado.txt
Linea: 1. El tag abierto, no fue cerrado.
root@:~/orgaTP1#
---------------------------------------------------------------------------
-Prueba de STDIN
root@:~/orgaTP1# echo "<hola> </hola>" | ./validate -i -
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# ./validate -i -
<hola> <tag2> esto es una prueba de anidados </tag2></hola>
root@:~/orgaTP1#
---------------------------------------------------------------------------
Hasta este momento, la corrida de pruebas venia bien pero nos encontramos
con este error.
root@:~/orgaTP1# echo "<hola>" | ./validate -i -
Linea: 1. El tag abierto, no fue cerrado.
Segmentation fault (core dumped)
root@:~/orgaTP1#
---------------------------------------------------------------------------
root@:~/orgaTP1# ./validate -i -
<hola> <tag2> esto es una prueba erronea de anidados </hola> <tag3>
Linea: 0. Tag mal anidado, el ultimo tag cerrado, no correspondecon el
ultimo tag abierto.
Segmentation fault (core dumped)
root@:~/orgaTP1#
---------------------------------------------------------------------------
Despues de buscar un rato y no encontrar solucion en el
codigo, decidimos usar gdb.
---------------------------------------------------------------------------
root@:~/orgaTP1# gdb validate validate.core
GNU gdb 5.3nb1
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "mipsel--netbsd"...
Core was generated by `validate'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/libexec/ld.elf_so...done.
Loaded symbols for /usr/libexec/ld.elf_so
Reading symbols from /usr/lib/libc.so.12...done.
Loaded symbols for /usr/lib/libc.so.12
#0 0x7dfb4508 in _rtld_exit () from /usr/libexec/ld.elf_so
(gdb)
---------------------------------------------------------------------------
Y nos encontramos como que el error estaba en el final de la ejecucion
del programa, o sea se imprime el mensaje de error pero en el medio entre
eso y el return 1 de la funcion ocurria el segmentation fault. Luego estuvimos
buscando un largo rato a ver si encontrabamos el problema pero al no
encontrar solucion lo dejamos asi.
Como se puede ver tanto el programa con archivos como por stdin
funcionan, vuelven normalmente y o retornar el mensaje por stderr en caso
de error, tanto en sus versiones C como Mips.
Una unica optimizacion posible seria poder encontrar el error que esta
causando que solo por stdin cuando termina de imprimir el error
hace que falle el programa.
\end{lstlisting}
\subsection{Código}
\subsubsection{Código en C}
\begin{lstlisting}[language=C, columns=flexible, breaklines=true, frame=single, title=Listing : validate.h]
#ifndef VALIDATE_H_
#define VALIDATE_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
#include "mymalloc.h"
extern int validate(char* text, char** errmsg);
extern int analizarTag(char* text, char* tagEncontrado, int pos, int *contadorLineas);
#endif /* VALIDATE_H_ */
\end{lstlisting}
\begin{lstlisting}[language=C, columns=flexible, breaklines=true, frame=single, title=Listing : validate.c]
#include "validate.h"
int analizarTag(char* text, char* tagEncontrado, int pos, int *contadorLineas)
{
while(text[pos] != '\0')
{
if(text[pos] == '\n')
{
(*contadorLineas)++;
}
if(text[pos] == '<')
{
pos++;
// Si entra en cerrar un tag
if(text[pos] == '/')
{
pos++;
int j = 0;
while((text[pos] != '>') && (tagEncontrado[j] == text[pos]))
{
j++; pos++;
}
if((tagEncontrado[j] == '\0') && (text[pos] == '>'))
{
return pos;
} else {
return -2;
}
} else {
int contadorTag = pos;
while(text[contadorTag] != '>')
{
contadorTag++;
}
contadorTag = contadorTag - pos;
contadorTag = contadorTag + 1; //Para el '\0' final
char* tagALevantar = (char*)malloc(sizeof(char)*contadorTag);
int k = 0;
while(text[pos] != '>')
{
tagALevantar[k] = text[pos];
k++; pos++;
}
tagALevantar[k] = '\0';
pos++;
pos = analizarTag(text, tagALevantar, pos, contadorLineas);
free(tagALevantar);
switch(pos)
{
case -1:
return -1;
break;
case -2:
return -2;
break;
default:
break;
}
}
}
pos++;
}
return -1;
}
int validate(char *text, char **errmsg){
char* buffer;
int i = 0;
int contadorLineas = 0;
while(text[i] != '\0')
{
if(text[i] == '\n')
{
contadorLineas++;
}
if(text[i] == '<')
{
i++;
int contadorTag = i;
while(text[contadorTag] != '>')
{
contadorTag++;
}
contadorTag = contadorTag - i;
contadorTag = contadorTag + 1; //Para el '\0' final
char* tagALevantar = (char*)malloc(sizeof(char)*contadorTag);
int j = 0;
while(text[i] != '>')
{
tagALevantar[j] = text[i];
j++; i++;
}
tagALevantar[j] = '\0';
i = analizarTag(text, tagALevantar, i, &contadorLineas);
free(tagALevantar);
switch(i)
{
case -1:
contadorLineas = contadorLineas + 1;
sprintf(buffer, "Linea: %d. El tag abierto, no fue cerrado.\n", contadorLineas);
*errmsg = buffer;
return 1;
break;
case -2:
contadorLineas = contadorLineas + 1;
sprintf(buffer, "Linea: %d. Tag mal anidado, el ultimo tag cerrado, no corresponde con el ultimo tag abierto.\n", contadorLineas);
*errmsg = buffer;
return 1;
break;
default:
break;
}
}
i++;
}
return 0;
}
\end{lstlisting}
\begin{lstlisting}[language=C, columns=flexible, breaklines=true, frame=single, title=Listing : main.c]
#include "validate.h"
void cargarArchivoAMemoria(FILE* archivoEntrada, char* text)
{
int actual = 0;
while(!feof(archivoEntrada)){
(text)[actual] = fgetc(archivoEntrada);
actual++;
}
(text)[actual - 1] = '\0';
}
//Funcion que imprime el manual del TP1
void printManual(){
printf("Usage:\n validate -h\n");
printf(" validate -V\n");
printf(" validate [options] file\n");
printf("Options:\n");
printf(" -h, --help Prints usage information.\n");
printf(" -V, --version Prints version information.\n");
printf(" -i, --input Path to input file (-i - for stdin)\n");
printf("Examples:\n");
printf(" validate -i -\n");
printf(" validate myfile.tagged\n");
printf(" validate -i myfile.tagged\n");
}
//Funcion para comprobar que los archivos se abrieron bien.
void checkFile(FILE* file){
if (file == NULL){
//Si hay error se escribe por stderr.
fprintf(stderr, "Error, nombre de archivo inexistente, el programa se cerrara.\n");
exit(1); // Se cierra el programa y se devuelve 1 por error.
}
}
//Funcion principal del TP1
int main(int argc, char* argv[]){
int next_option;
const char* const short_options = "i:hV";
const struct option long_options[] = {
{ "input", 1, NULL, 'i' },
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'V' },
{ NULL, 0, NULL, 0 } /* Necesario al final del array. */
};
//Aca por defecto se establecen algunos parametros.
//Luego depende las opciones elegidas se van cambiando.
FILE* archivoEntrada = stdin;
const char* nombreArchivo;
int ejecutar = 0;
int flag;
char* errmsg;
int tamanio = 2048;
char text[tamanio];
//Procesamiento de los parametros de entrada.
do {
next_option = getopt_long(argc, argv, short_options, long_options, NULL);
switch (next_option){
case 'i': /* -i, --input */
/* Indica el archivo de entrada a utilizar (-i - for stdin) */
if (strcmp(optarg, "-") != 0){
nombreArchivo = optarg;
archivoEntrada = fopen(nombreArchivo, "r");
checkFile(archivoEntrada);
cargarArchivoAMemoria(archivoEntrada, text);
fclose(archivoEntrada);
}else {
cargarArchivoAMemoria(archivoEntrada, text);
}
ejecutar = 1;
break;
case 'h': /* -h, --help */
/* Imprime el menu de ayuda */
printManual();
return 0;
break;
case 'V': /* -V, --version */
/* Prints version information. */
printf(" Version 1.0 del TP1\n");
exit(0);
break;
case -1: /* Se terminaron las opciones */
break;
default: /* Opcion incorrecta */
fprintf(stderr, "Error, opcion incorrecta, el programa se cerrara.\n");
printManual(); //Se imprime el manual para que se vean las opciones correctas.
exit(1); // Se cierra el programa y se devuelve 1 por error.
}
} while (next_option != -1);
if (argc == (optind + 1)){
nombreArchivo = argv[optind];
archivoEntrada = fopen(nombreArchivo, "r");
checkFile(archivoEntrada);
cargarArchivoAMemoria(archivoEntrada, text);
fclose(archivoEntrada);
ejecutar = 1;
}
//Arranca la ejecucion del programa.
if (ejecutar){
//Se llama a la funcion validate.
// *text es un puntero al texto contenido en el archivo.
// **errmsg es un puntero a un array de caracteres, a llenar por la funcion validate en caso de error.
//Se utiliza la variable flag para ver si hubo error o no en la validacion.
//La funcion debe retornar 0 en caso de que la validacion sea correcta, o 1 en caso de que no.
flag = validate(text, &errmsg);
if (flag>0){
fprintf(stderr, "\n%s\n", errmsg);
return 1;
}
} else {
fprintf(stderr, "Error, accion invalida, el programa se cerrara.\n");
printManual(); //Se imprime el manual para que se vean las opciones correctas.
return 1; // Se cierra el programa y se devuelve 1 por error.
}
return 0;
}
\end{lstlisting}
\subsubsection{Código en Mips}
\begin{lstlisting}[ columns=flexible, breaklines=true, frame=single, title=Listing : validate.S]
#include <mips/regdef.h>
#include <sys/syscall.h>
#Argumentos de la funcion
#define VALIDATE_ARG1 60
#define VALIDATE_ARG0 56
#Stack Size
#define VALIDATE_SS 56
#SRA
#define VALIDATE_RA 48
#define VALIDATE_FP 44
#define VALIDATE_GP 40
#LTA
#define VALIDATE_RT 36
#define VALIDATE_BF 32
#define VALIDATE_TAGL 28
#define VALIDATE_J 24
#define VALIDATE_CL 20
#define VALIDATE_I 16
#ABA
#define ABA_3 12
#define ABA_2 8
#define ABA_1 4
#define ABA_0 0
#Constantes
#define FIN_TEXTO 0
#define SALTO_DE_LINEA 10
#define MENOR 60
#define MAYOR 62
.data
.align 2
ER_TAG_MAL_CERRADO:
.ascii "Linea: %d. El tag abierto, no fue cerrado.\n\0"
.align 2
ER_TAG_MAL_ANIDADO:
.ascii "Linea: %d. Tag mal anidado, el ultimo tag cerrado, no corresponde"
.ascii "con el ultimo tag abierto.\n\0"
.text
.align 2
.globl validate
.ent validate
validate:
.frame $fp, VALIDATE_SS, ra
.set noreorder
.cpload t9
.set reorder
#Creo el stack frame
subu sp, sp, VALIDATE_SS
.cprestore VALIDATE_GP
sw ra, VALIDATE_RA(sp)
sw $fp,VALIDATE_FP(sp)
sw gp, VALIDATE_GP(sp)
move $fp,sp
sw a0, VALIDATE_ARG0($fp)
sw a1, VALIDATE_ARG1($fp)
sw zero, VALIDATE_I($fp) # i = 0
sw zero, VALIDATE_CL($fp) # contadorLineas = 0
whileFinLinea:
lw t1, VALIDATE_ARG0($fp) # t1 = *text
lw t0, VALIDATE_I($fp) # t0 = i
addu t6, t0, t1 # Cargo direc te text[i] en t6
lbu t6, 0(t6) # t6 = text[i]
li t2, FIN_TEXTO
bne t6, t2, ifFinLinea # Si text[i] != \0 voy a ifFinLinea
b return_0
ifFinLinea:
lw t1, VALIDATE_ARG0($fp) # t1 = *text
lw t0, VALIDATE_I($fp) # t0 = i
addu t6, t0, t1 # Cargo direc te text[i] en t6
lbu t6, 0(t6) # t6 = text[i]
li t2, SALTO_DE_LINEA # t2 = \n
bne t6,t2, ifMenor # (if text[i] != \n)
lw t3,VALIDATE_CL($fp) # t3 -> contador
addu t3, t3, 1 #contadorLinea++
sw t3,VALIDATE_CL($fp) #Almaceno el contadorLinea modificado en el stack
ifMenor:
lw t1, VALIDATE_ARG0($fp) # t1 = *text
lw t0, VALIDATE_I($fp) # t0 = i
addu t6, t0, t1 # Cargo direc te text[i] en t6
lbu t6, 0(t6) # t6 = text[i]
li t2, MENOR # t2 = <
bne t6, t2, incrementarPos #Si no son iguales incremento la posicion
lw t0, VALIDATE_I($fp) #Cargo el valor de i almacenado en el stack
addu t0, t0,1 # i++
sw t0, VALIDATE_I($fp)
lw t0, VALIDATE_I($fp) #Cargo la i
sw t0, VALIDATE_TAGL($fp) #contadorTag = i
contadorTag:
lw t1, VALIDATE_ARG0($fp) # t1 = *text
lw t0, VALIDATE_TAGL($fp) # t0 = contadorTag
addu t6, t0, t1 # Cargo direc te text[i] en t6
lb t6, 0(t6) # t6 = text[i]
li t2, MAYOR
bne t6, t2, aumentarConTag #Distino de fin de texto
lw t2, VALIDATE_TAGL($fp) #t2 = contadorTag
lw t0, VALIDATE_I($fp) #t0 = i
subu t7, t2, t0 #contadorTag = contadorTag - i
addu t7, t7, 1 #contadorTag = contadorTag + 1 para el '\0'
sw t7, VALIDATE_TAGL($fp)
lw a0, VALIDATE_TAGL($fp) #Cargo el argunmento de la funcion
la t9, mymalloc #Cargo en t9 la direccion de la funcion
jal t9 #llamo a la funcion malloc
sw v0, VALIDATE_TAGL($fp) #guardo la posicion de memoria que reserve
sw zero,VALIDATE_J($fp) # j = 0
whileNotFinTag:
lw t1, VALIDATE_ARG0($fp) # t1 = *text
lw t0, VALIDATE_I($fp) #Cargo el valor de i almacenado en el stack
addu t6, t1, t0 #Muevo el texto a la nueva i
lbu t6, 0(t6) # text[i]
li t2, MAYOR #Cargo en t2 >
bne t6, t2, tagALevantar # text[i] != '>'
lw t4, VALIDATE_TAGL($fp) #Almaceno memoria para tagALevantar
lw t5, VALIDATE_J($fp) #Almacento en t5 j
addu t8, t4, t5 #Cargo en a0 la direccion de tagALevantar[j]
li t2, FIN_TEXTO #Cargo en t2 \0
sb t2, 0(t8) #tagALevantar[j] = '\0'
b switchValidate
aumentarConTag:
lw t0,VALIDATE_TAGL($fp)
addu t0,t0,1 #contadorTag++
sw t0,VALIDATE_TAGL($fp)
b contadorTag
tagALevantar:
#Para cargar tagALevantar[j]
lw t4, VALIDATE_TAGL($fp) #Cargo tag a levantar del stack
lw t5, VALIDATE_J($fp) #Cargo en t5 j, j = 0
addu t8, t4,t5 #Almacento en t8 la direc de de memoria de tagALevantar[j]
#Para cargar text[i]
lw t1, VALIDATE_ARG0($fp) # t1 = *text
lw t0, VALIDATE_I($fp) #Cargo el valor de i almacenado en el stack
addu t6, t1,t0 # Almaceno la dir de memoria de text[i]
# tagALevantar[j] = text[i];
lb t6, 0(t6) # t6 = text[i]
sb t6, 0(t8) # tagALevantar[j] = text[i];
#j++
lw t5, VALIDATE_J($fp) #Cargo en t5 j, j = 0
addiu t5, t5,1 #j++
sw t5, VALIDATE_J($fp) #Almaceno el valor de j en el stack
#i++
lw t0, VALIDATE_I($fp) #Cargo en t0 i
addiu t0, t0,1 #i++
sw t0, VALIDATE_I($fp) #Almaceno el valor de i en el stack
b whileNotFinTag
switchValidate:
lw a0, VALIDATE_ARG0($fp) #Cargo en a0 *text
lw a1, VALIDATE_TAGL($fp) #Cargo en a1 tagALevantar
lw a2, VALIDATE_I($fp) #Cargo en a2 la posicion
la a3, VALIDATE_CL($fp) #Cargo en a3 el contadorLinea
la t9, analizarTag #Cargo la direccion de analizarTag en t9
jal t9
sw v0, VALIDATE_I($fp) #Almaceno en el stack lo que me devuelve analizarTag
#Cargo argumento - FREE
lw a0, VALIDATE_TAGL($fp) #Cargo en a1 la seccion a liberar
la t9, myfree
jal t9
#Sigo con el fin del programa
lw t0, VALIDATE_I($fp) #Cargo en t0 i
#Arranca el switch
li t6, -2 #Cargo en t6 -2
beq t0, t6, errorAnidado # Si i = -2 voy a errorAnidado
li t6, -1 #Cargo en t6 -1
beq t0, t6, errorNoCerrado # si i = -1 voy a errorNoCerrado
b incrementarPos #Va a default
errorNoCerrado:
lw a0, VALIDATE_BF($fp) #Cargo en a0 el buffer
la a1, ER_TAG_MAL_CERRADO #Cargo en a1 la direcc de tag mal cerrado
lw a2, VALIDATE_CL($fp) #Cargo en a2 contador lineas
la t9, sprintf #Cargo la direccion de sprintf en t9
jal t9
lw t0, VALIDATE_ARG1($fp) #Cargo en t0 *errmsg
lw t1, VALIDATE_BF($fp) #Cargo en t1 el *buffer
sw t1, 0(t0) #*errmsg = buffer
li v0, 1 #v0 = 1
sw v0, VALIDATE_RT($fp) #return 1
b liberarStack
errorAnidado:
lw a0, VALIDATE_BF($fp) #Cargo en a0 el buffer
la a1, ER_TAG_MAL_ANIDADO #Cargo en a1 la direc de tag mal anidado
lw a2, VALIDATE_CL($fp) #Cargo en a2 contador lineas
la t9, sprintf #Cargo la direccion de sprintf en t9
jal t9
lw t0, VALIDATE_ARG1($fp) #Cargo en t0 *errmsg
lw t1, VALIDATE_BF($fp) #Cargo en t1 el *buffer
sw t1, 0(t0) #*errmsg = buffer
li v0, 1 #v0 = 1
sw v0, VALIDATE_RT($fp) #return 1
b liberarStack
incrementarPos:
lw t0, VALIDATE_I($fp) #Cargo en t0 el valor de i
addu t0, t0, 1 # i++
sw t0, VALIDATE_I($fp) #Lo almaceno en el stack
b whileFinLinea
return_0:
sw zero,VALIDATE_RT($fp)
liberarStack:
#Destruye stack frame
lw v0, VALIDATE_RT($fp)
move sp, $fp
lw ra, VALIDATE_RA(sp)
lw $fp,VALIDATE_FP(sp)
lw gp, VALIDATE_GP(sp)
addu sp, sp,VALIDATE_SS
j ra
.end validate
\end{lstlisting}
\begin{lstlisting}[ columns=flexible, breaklines=true, frame=single, title=Listing : analizartag.S]
#include <mips/regdef.h>
#include <sys/syscall.h>
#Argumentos de la funcion
#define ATAG_ARG3 52
#define ATAG_ARG2 48
#define ATAG_ARG1 44
#define ATAG_ARG0 40
#Stack Size
#define ATAG_SS 40
#SRA
#define ATAG_RA 32
#define ATAG_FP 28
#define ATAG_GP 24
#LTA
#define TAG_A_LEVANTAR 16
#define VAR_AUX 20
#ABA
#define ABA_3 12
#define ABA_2 8
#define ABA_1 4
#define ABA_0 0
#Constantes
#define FIN_TEXTO 0
#define SALTO_DE_LINEA 10
#define BARRA 47
#define MENOR 60
#define MAYOR 62
.text
.align 2
.globl analizarTag
.ent analizarTag
analizarTag:
.frame $fp, ATAG_SS, ra
.set noreorder
.cpload t9
.set reorder
#Creo el stack frame
subu sp, sp, ATAG_SS
.cprestore ATAG_GP
sw ra, ATAG_RA(sp)
sw $fp,ATAG_FP(sp)
sw gp, ATAG_GP(sp)
move $fp, sp
sw a0,ATAG_ARG0($fp)
sw a1,ATAG_ARG1($fp)
sw a2,ATAG_ARG2($fp)
sw a3,ATAG_ARG3($fp)
whileDistintoDeEnd:
lw t0, ATAG_ARG0($fp) #Cargo la direc el texto
lw t1, ATAG_ARG2($fp) #Cargo la pos
addu t0, t0,t1 #Muevo la direc del texto a la pos
lb t0, 0(t0) #Cargo el texto en la pos(cargo un char)
li t6, FIN_TEXTO #Cargo el fin de texto
bne t0, t6,verSiEsSaltoDeLinea #Distino de fin de texto
b errorNoCerrado #LLegue al fin del texto y no cerre el tag
verSiEsSaltoDeLinea:
lw t0, ATAG_ARG0($fp) #Cargo la direc el texto
lw t1, ATAG_ARG2($fp) #Cargo la pos
addu t0, t0,t1 #Muevo la direc del texto a la pos
lb t0, 0(t0) #Cargo el texto en la pos(cargo un char)
li t6, SALTO_DE_LINEA #Cargo el salto de linea
bne t0, t6,verSiComienzaTag #Si no es salto de linea, salta a analizar si empieza un tag
#Si es igual a salto de linea, tengo que sumar uno al contador de lineas
lw t3, ATAG_ARG3($fp) #Cargo la direccion de contadorLineas
lw t6, ATAG_ARG3($fp) #Cargo un auxiliar para no perder la referencia
lw t6, 0(t6) #Cargo contadorLineas(int)
addu t6, t6,1 #Le sumo uno a contadorLineas
sw t6, 0(t3) #Guardo en la direc de contadorLineas, contadorLineas + 1
verSiComienzaTag:
lw t0, ATAG_ARG0($fp) #Cargo la direc el texto
lw t1, ATAG_ARG2($fp) #Cargo la pos
addu t0, t0,t1 #Muevo la direc del texto a la pos
lb t0, 0(t0) #Cargo el texto en la pos(cargo un char)
li t6, MENOR #Cargo el MENOR '<'
beq t0, t6,comienzaTag #Si es igual a '<'salto a comienzaTag
# Si es distinto de '<' tengo que sumar uno a pos y volver al principio
lw t1, ATAG_ARG2($fp) #Cargo pos
addu t1, t1,1 #Si es distinto, le sumo uno a la pos
sw t1, ATAG_ARG2($fp) #Guardo pos++
b whileDistintoDeEnd #Vuelvo al principio
comienzaTag:
#Antes encontre un '<', tengo que saltearlo sumandole uno a pos
lw t1, ATAG_ARG2($fp) #Cargo pos
addu t1, t1,1 #Le sumo uno a pos
sw t1, ATAG_ARG2($fp) #Guardo pos++
lw t0, ATAG_ARG0($fp) #Cargo la direc del texto
lw t1, ATAG_ARG2($fp) #Cargo la pos acutal
addu t0, t1,t0 #Muevo la direc del texto a la pos
lbu t0, 0(t0) #Cargo el texto en la pos(cargo un char)
li t6, BARRA #Cargo la BARRA '/'
bne t0, t6, hayNuevoTag #Si text[pos] no es igual a la barra empieza un nuevo tag anidado
#Si habia una barra, tengo que saltearla sumandole uno a pos
lw t1, ATAG_ARG2($fp) #Cargo pos
addu t1, t1,1 #Le sumo uno a pos
sw t1, ATAG_ARG2($fp) #Guardo pos++
sw zero,20($fp) #j = 0 (Con j itero por el tagLevantado)
#Despues de saltear la barra analizo si el tag que me pasaron es igual al que estoy encontrando
whileDistintoDeCerrarTag:
lw t0, ATAG_ARG0($fp) #Cargo la direc del texto
lw t1, ATAG_ARG2($fp) #Cargo pos
addu t0, t1,t0 #Muevo la direc del texto a la pos
lb t0, 0(t0) #Cargo el texto en la pos(cargo un char)
li t6, MAYOR #Cargo el MAYOR '>'
beq t0, t6, finCerrarTag #Si text[pos] == '>' salto a finCerrarTag
#llegue al final del tag y voy a analizar si eran iguales
#Cargo tagEncontrado[j]
lw t2, ATAG_ARG1($fp) #Cargo el tagEncontrado