summaryrefslogtreecommitdiffstats
path: root/po/it.po
blob: 455707030713eeb2e4e61cea5dd7258e0f8b19c5 (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
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
# translation of it.po to Italian
# Copyright (C) 2000, 2001 Mandriva S.A.
#
# Paolo Lorenzin <pasusu@tin.it>, 2000.
# Simone Riccio <s.riccio@aeb-informatica.it>, 2002.
# Roberto Rosselli Del Turco <rosselli@ling.unipi.it>, 2001, 2002,2003.
# Marco De Vitis <mdv@spin.it>, 2003.
# Andrea Celli <a.celli@caltanet.it>, 2003, 2004, 2005, 2006.
# Giuseppe Levi <giuseppe.levi@email.it>, 2005.
# Andrea Celli <andrea.celli@libero.it>, 2007.
msgid ""
msgstr ""
"Project-Id-Version: it\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-07-02 17:45+0800\n"
"PO-Revision-Date: 2007-09-13 23:09+0200\n"
"Last-Translator: Andrea Celli <andrea.celli@libero.it>\n"
"Language-Team: Italian <timl@freelists.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n"

#: ../lib/Xconfig/card.pm:19
#, c-format
msgid "256 kB"
msgstr "256 KB"

#: ../lib/Xconfig/card.pm:20
#, c-format
msgid "512 kB"
msgstr "512 KB"

#: ../lib/Xconfig/card.pm:21
#, c-format
msgid "1 MB"
msgstr "1 MB"

#: ../lib/Xconfig/card.pm:22
#, c-format
msgid "2 MB"
msgstr "2 MB"

#: ../lib/Xconfig/card.pm:23
#, c-format
msgid "4 MB"
msgstr "4 MB"

#: ../lib/Xconfig/card.pm:24
#, c-format
msgid "8 MB"
msgstr "8 MB"

#: ../lib/Xconfig/card.pm:25
#, c-format
msgid "16 MB"
msgstr "16 MB"

#: ../lib/Xconfig/card.pm:26
#, c-format
msgid "32 MB"
msgstr "32 MB"

#: ../lib/Xconfig/card.pm:27
#, c-format
msgid "64 MB or more"
msgstr "64 MB o più"

#: ../lib/Xconfig/card.pm:175
#, c-format
msgid "X server"
msgstr "Server X"

#: ../lib/Xconfig/card.pm:176
#, c-format
msgid "Choose an X server"
msgstr "Scegli un server X"

#: ../lib/Xconfig/card.pm:207
#, c-format
msgid "Multi-head configuration"
msgstr "Configurazione multi-monitor"

#: ../lib/Xconfig/card.pm:208
#, c-format
msgid ""
"Your system supports multiple head configuration.\n"
"What do you want to do?"
msgstr ""
"Il tuo sistema permette la configurazione di più monitor.\n"
"Cosa vuoi fare?"

#: ../lib/Xconfig/card.pm:279
#, c-format
msgid "Select the memory size of your graphics card"
msgstr "Indica la quantità di memoria della scheda grafica"

#: ../lib/Xconfig/card.pm:304
#, c-format
msgid ""
"There is a proprietary driver available for your video card which may "
"support additional features.\n"
"Do you wish to use it?"
msgstr ""
"Esiste un driver proprietario disponibile per questa scheda video che ha "
"ulteriori caratteristiche.\n"
"Vuoi utilizzarlo?"

#: ../lib/Xconfig/card.pm:331
#, c-format
msgid ""
"The proprietary driver was not properly installed, defaulting to free "
"software driver."
msgstr ""
"Il driver proprietario non ha potuto essere installato correttamente, "
"in mancanza verrà usato il driver libero."

#: ../lib/Xconfig/card.pm:398
#, c-format
msgid "Configure all heads independently"
msgstr "Configurare tutti gli schermi indipendentemente"

#: ../lib/Xconfig/card.pm:399
#, c-format
msgid "Use Xinerama extension"
msgstr "Usa l'estensione Xinerama"

#: ../lib/Xconfig/card.pm:404
#, c-format
msgid "Configure only card \"%s\"%s"
msgstr "Configura solo la scheda \"%s\" %s"

#: ../lib/Xconfig/main.pm:91 ../lib/Xconfig/main.pm:92
#: ../lib/Xconfig/monitor.pm:115
#, c-format
msgid "Custom"
msgstr "Personalizzato"

#: ../lib/Xconfig/main.pm:126
#, c-format
msgid "Graphic Card & Monitor Configuration"
msgstr "Configurazione della scheda video e del monitor"

#: ../lib/Xconfig/main.pm:127
#, c-format
msgid "Quit"
msgstr "Esci"

#: ../lib/Xconfig/main.pm:129
#, c-format
msgid "Graphic Card"
msgstr "Scheda grafica"

#: ../lib/Xconfig/main.pm:132 ../lib/Xconfig/monitor.pm:109
#, c-format
msgid "Monitor"
msgstr "Monitor"

#: ../lib/Xconfig/main.pm:135 ../lib/Xconfig/resolution_and_depth.pm:312
#, c-format
msgid "Resolution"
msgstr "Risoluzione"

#: ../lib/Xconfig/main.pm:138
#, c-format
msgid "Test"
msgstr "Prova"

#: ../lib/Xconfig/main.pm:143
#, c-format
msgid "Options"
msgstr "Opzioni"

#: ../lib/Xconfig/main.pm:148
#, c-format
msgid "Plugins"
msgstr "Plugin"

#: ../lib/Xconfig/main.pm:182
#, c-format
msgid "Your Xorg configuration file is broken, we will ignore it."
msgstr "Il file di configurazione Xorg è danneggiato, verrà ignorato."

#: ../lib/Xconfig/main.pm:201
#, c-format
msgid ""
"Keep the changes?\n"
"The current configuration is:\n"
"\n"
"%s"
msgstr ""
"Conservo le modifiche apportate?\n"
"La configurazione attuale è:\n"
"\n"
"%s"

#: ../lib/Xconfig/monitor.pm:110
#, c-format
msgid "Choose a monitor for head #%d"
msgstr "Scegli un monitor per l'head n. %d"

#: ../lib/Xconfig/monitor.pm:110
#, c-format
msgid "Choose a monitor"
msgstr "Scegli un monitor"

#: ../lib/Xconfig/monitor.pm:116
#, c-format
msgid "Plug'n Play"
msgstr "Plug'n Play"

#: ../lib/Xconfig/monitor.pm:117 ../lib/mouse.pm:47
#, c-format
msgid "Generic"
msgstr "Generico"

#: ../lib/Xconfig/monitor.pm:118
#, c-format
msgid "Vendor"
msgstr "Marca"

#: ../lib/Xconfig/monitor.pm:128
#, c-format
msgid "Plug'n Play probing failed. Please select the correct monitor"
msgstr "Il rilevamento Plug'n Play non è riuscito. Indica il modello del monitor."

#: ../lib/Xconfig/monitor.pm:136
#, c-format
msgid ""
"The two critical parameters are the vertical refresh rate, which is the "
"rate\n"
"at which the whole screen is refreshed, and most importantly the horizontal\n"
"sync rate, which is the rate at which scanlines are displayed.\n"
"\n"
"It is VERY IMPORTANT that you do not specify a monitor type with a sync "
"range\n"
"that is beyond the capabilities of your monitor: you may damage your "
"monitor.\n"
" If in doubt, choose a conservative setting."
msgstr ""
"I due parametri critici sono la frequenza di refresh verticale, che è la\n"
"frequenza con cui l'intero schermo è aggiornato, e ancora più importante\n"
"la frequenza di sincronia orizzontale, che è la frequenza con cui vengono\n"
"mostrate le linee di scansione. \n"
"\n"
"È MOLTO IMPORTANTE non indicare un tipo di monitor con un intervallo di\n"
"frequenze superiore alle capacità del monitor usato: lo si potrebbe "
"danneggiare.\n"
"Se hai dubbi, scegli le impostazioni più caute."

#: ../lib/Xconfig/monitor.pm:143
#, c-format
msgid "Horizontal refresh rate"
msgstr "Frequenza di refresh orizzontale"

#: ../lib/Xconfig/monitor.pm:144
#, c-format
msgid "Vertical refresh rate"
msgstr "Frequenza di refresh verticale"

#: ../lib/Xconfig/plugins.pm:219
#, c-format
msgid "Choose plugins"
msgstr "Scegli i plugin"

#: ../lib/Xconfig/resolution_and_depth.pm:10
#, c-format
msgid "256 colors (8 bits)"
msgstr "256 colori (8 bit)"

#: ../lib/Xconfig/resolution_and_depth.pm:11
#, c-format
msgid "32 thousand colors (15 bits)"
msgstr "32 mila colori (15 bit)"

#: ../lib/Xconfig/resolution_and_depth.pm:12
#, c-format
msgid "65 thousand colors (16 bits)"
msgstr "65 mila colori (16 bit)"

#: ../lib/Xconfig/resolution_and_depth.pm:13
#, c-format
msgid "16 million colors (24 bits)"
msgstr "16 milioni di colori (24 bit)"

#: ../lib/Xconfig/resolution_and_depth.pm:128
#, c-format
msgid "Resolutions"
msgstr "Risoluzioni"

#: ../lib/Xconfig/resolution_and_depth.pm:334 ../lib/mouse.pm:184
#, c-format
msgid "Other"
msgstr "Altro"

#: ../lib/Xconfig/resolution_and_depth.pm:383
#, c-format
msgid "Choose the resolution and the color depth"
msgstr "Scegli risoluzione e profondità di colore"

#: ../lib/Xconfig/resolution_and_depth.pm:384
#, c-format
msgid "Graphics card: %s"
msgstr "Scheda grafica: %s"

#: ../lib/Xconfig/resolution_and_depth.pm:398
#, c-format
msgid "Ok"
msgstr "OK"

#: ../lib/Xconfig/resolution_and_depth.pm:398
#, c-format
msgid "Cancel"
msgstr "Annulla"

#: ../lib/Xconfig/resolution_and_depth.pm:398
#, c-format
msgid "Help"
msgstr "Guida"

#: ../lib/Xconfig/test.pm:30
#, c-format
msgid "Test of the configuration"
msgstr "Prova della configurazione"

#: ../lib/Xconfig/test.pm:31
#, c-format
msgid "Do you want to test the configuration?"
msgstr "Vuoi provare la configurazione?"

#: ../lib/Xconfig/test.pm:31
#, c-format
msgid "Warning: testing this graphic card may freeze your computer"
msgstr "Attenzione: il test di questa scheda video può bloccare il computer"

#: ../lib/Xconfig/test.pm:69
#, c-format
msgid ""
"An error occurred:\n"
"%s\n"
"Try to change some parameters"
msgstr ""
"Si è verificato un errore:\n"
"%s\n"
"Prova a cambiare dei parametri"

#: ../lib/Xconfig/test.pm:130
#, c-format
msgid "Leaving in %d seconds"
msgstr "Uscita tra %d secondi"

#: ../lib/Xconfig/test.pm:130
#, c-format
msgid "Is this the correct setting?"
msgstr "È l'impostazione corretta?"

#: ../lib/Xconfig/various.pm:26
#, c-format
msgid "3D hardware acceleration: %s\n"
msgstr "Accelerazione hardware 3d: %s\n"

#: ../lib/Xconfig/various.pm:27
#, c-format
msgid "Keyboard layout: %s\n"
msgstr "Tipo di tastiera: %s\n"

#: ../lib/Xconfig/various.pm:28
#, c-format
msgid "Mouse type: %s\n"
msgstr "Tipo di mouse: %s\n"

#: ../lib/Xconfig/various.pm:30
#, c-format
msgid "Monitor: %s\n"
msgstr "Monitor: %s\n"

#: ../lib/Xconfig/various.pm:31
#, c-format
msgid "Monitor HorizSync: %s\n"
msgstr "Frequenza orizzontale del monitor: %s\n"

#: ../lib/Xconfig/various.pm:32
#, c-format
msgid "Monitor VertRefresh: %s\n"
msgstr "Refresh verticale del monitor: %s\n"

#: ../lib/Xconfig/various.pm:34
#, c-format
msgid "Graphics card: %s\n"
msgstr "Scheda grafica: %s\n"

#: ../lib/Xconfig/various.pm:35
#, c-format
msgid "Graphics memory: %s kB\n"
msgstr "Memoria scheda grafica: %s KB\n"

#: ../lib/Xconfig/various.pm:37
#, c-format
msgid "Color depth: %s\n"
msgstr "Profondità di colore: %s\n"

#: ../lib/Xconfig/various.pm:38
#, c-format
msgid "Resolution: %s\n"
msgstr "Risoluzione: %s\n"

#: ../lib/Xconfig/various.pm:40
#, c-format
msgid "Xorg driver: %s\n"
msgstr "Driver Xorg: %s\n"

#: ../lib/Xconfig/various.pm:204
#, c-format
msgid "Xorg configuration"
msgstr "Configurazione di Xorg"

#: ../lib/Xconfig/various.pm:205
#, c-format
msgid "Graphic card options"
msgstr "Opzioni scheda grafica"

#: ../lib/Xconfig/various.pm:207
#, c-format
msgid "3D hardware acceleration"
msgstr "Accelerazione hardware 3d"

#: ../lib/Xconfig/various.pm:209
#, c-format
msgid "Enable Translucency (Composite extension)"
msgstr "Abilita Translucency (estensione Composite)"

#: ../lib/Xconfig/various.pm:212
#, c-format
msgid "Use hardware accelerated mouse pointer"
msgstr "Usare l'accelerazione hardware per il puntatore del mouse"

#: ../lib/Xconfig/various.pm:215
#, c-format
msgid "Enable RENDER Acceleration (this may cause bugs displaying text)"
msgstr ""
"Abilitata l'accelerazione RENDER (può causare problemi nella presentazione "
"del testo)"

#: ../lib/Xconfig/various.pm:219
#, c-format
msgid "Enable duplicate display on the external monitor"
msgstr "Abilita doppia visualizzazione sul monitor esterno"

#: ../lib/Xconfig/various.pm:220
#, c-format
msgid "Enable duplicate display on the second display"
msgstr "Abilita doppia visualizzazione sul secondo display"

#: ../lib/Xconfig/various.pm:223
#, c-format
msgid "Enable BIOS hotkey for external monitor switching"
msgstr "Abilita un hotkey BIOS per commutare su monitor esterno"

#: ../lib/Xconfig/various.pm:226
#, c-format
msgid "Use EXA instead of XAA (better performance for Render and Composite)"
msgstr "Usare EXA invece di XAA (migliori prestazioni di Render e Composito)"

#: ../lib/Xconfig/various.pm:228
#, c-format
msgid "Graphical interface at startup"
msgstr "Avvio con interfaccia grafica"

#: ../lib/Xconfig/various.pm:229
#, c-format
msgid "Automatically start the graphical interface (Xorg) upon booting"
msgstr "Avviare l'interfaccia grafica (Xorg) al boot"

#: ../lib/Xconfig/various.pm:241
#, c-format
msgid ""
"Your graphic card seems to have a TV-OUT connector.\n"
"It can be configured to work using frame-buffer.\n"
"\n"
"For this you have to plug your graphic card to your TV before booting your "
"computer.\n"
"Then choose the \"TVout\" entry in the bootloader\n"
"\n"
"Do you have this feature?"
msgstr ""
"La scheda grafica sembra disporre di un connettore TV-OUT.\n"
"Può essere configurata per funzionare usando il frame-buffer.\n"
"\n"
"Per farlo devi connettere la scheda grafica ad un televisore prima di "
"avviare il computer.\n"
"Poi scegli l'opzione \"TVout\" nella schermata del bootloader.\n"
"\n"
"È presente questa opzione?"

#: ../lib/Xconfig/various.pm:253
#, c-format
msgid "What norm is your TV using?"
msgstr "Che normativa viene utilizzata per la TV?"

#: ../lib/Xconfig/various.pm:348
#, c-format
msgid ""
"The display resolution being used may not be correct. \n"
"\n"
"If your desktop appears to stretch beyond the edges of the display, \n"
"installing %s may help fix the problem. Install it now?"
msgstr ""
"La risoluzione grafica che si sta utilizzando può non essere corretta.\n"
"\n"
"Se il vostro desktop sembra allungarsi oltre i bordi dello schermo, \n"
"l'installazione di %s può aiutare a correggere il problema. Procedere?"

#: ../lib/Xconfig/xfree.pm:770
#, c-format
msgid ""
"_:weird aspect ratio\n"
"other"
msgstr "altro"

#: ../lib/keyboard.pm:183 ../lib/keyboard.pm:215
#, c-format
msgid ""
"_: keyboard\n"
"Czech (QWERTZ)"
msgstr "Ceca (QWERTZ)"

#: ../lib/keyboard.pm:184 ../lib/keyboard.pm:217
#, c-format
msgid ""
"_: keyboard\n"
"German"
msgstr "Tedesca"

#: ../lib/keyboard.pm:185
#, c-format
msgid ""
"_: keyboard\n"
"Dvorak"
msgstr "Dvorak"

#: ../lib/keyboard.pm:186 ../lib/keyboard.pm:229
#, c-format
msgid ""
"_: keyboard\n"
"Spanish"
msgstr "Spagnola"

#: ../lib/keyboard.pm:187 ../lib/keyboard.pm:230
#, c-format
msgid ""
"_: keyboard\n"
"Finnish"
msgstr "Finlandese"

#: ../lib/keyboard.pm:188 ../lib/keyboard.pm:232
#, c-format
msgid ""
"_: keyboard\n"
"French"
msgstr "Francese"

#: ../lib/keyboard.pm:189 ../lib/keyboard.pm:233
#, c-format
msgid "UK keyboard"
msgstr "Tastiera UK"

#: ../lib/keyboard.pm:190 ../lib/keyboard.pm:278
#, c-format
msgid ""
"_: keyboard\n"
"Norwegian"
msgstr "Norvegese"

#: ../lib/keyboard.pm:191
#, c-format
msgid ""
"_: keyboard\n"
"Polish"
msgstr "Polacca"

#: ../lib/keyboard.pm:192 ../lib/keyboard.pm:288
#, c-format
msgid ""
"_: keyboard\n"
"Russian"
msgstr "Russa"

#: ../lib/keyboard.pm:193 ../lib/keyboard.pm:290
#, c-format
msgid ""
"_: keyboard\n"
"Swedish"
msgstr "Svedese"

#: ../lib/keyboard.pm:194 ../lib/keyboard.pm:325
#, c-format
msgid "US keyboard"
msgstr "Tastiera US"

#: ../lib/keyboard.pm:196
#, c-format
msgid ""
"_: keyboard\n"
"Albanian"
msgstr "Albanese"

#: ../lib/keyboard.pm:197
#, c-format
msgid ""
"_: keyboard\n"
"Armenian (old)"
msgstr "Armena (vecchia)"

#: ../lib/keyboard.pm:198
#, c-format
msgid ""
"_: keyboard\n"
"Armenian (typewriter)"
msgstr "Armena (macchina da scrivere)"

#: ../lib/keyboard.pm:199
#, c-format
msgid ""
"_: keyboard\n"
"Armenian (phonetic)"
msgstr "Armena (fonetica)"

#: ../lib/keyboard.pm:200
#, c-format
msgid ""
"_: keyboard\n"
"Arabic"
msgstr "Araba"

#: ../lib/keyboard.pm:201
#, c-format
msgid ""
"_: keyboard\n"
"Azerbaidjani (latin)"
msgstr "Azera (latina)"

#: ../lib/keyboard.pm:202
#, c-format
msgid ""
"_: keyboard\n"
"Belgian"
msgstr "Belga"

#: ../lib/keyboard.pm:203
#, c-format
msgid ""
"_: keyboard\n"
"Bengali (Inscript-layout)"
msgstr "Bengalese (mappa Inscript)"

#: ../lib/keyboard.pm:204
#, c-format
msgid ""
"_: keyboard\n"
"Bengali (Probhat)"
msgstr "Bengalese (mappa Probhat)"

#: ../lib/keyboard.pm:205
#, c-format
msgid ""
"_: keyboard\n"
"Bulgarian (phonetic)"
msgstr "Bulgara (fonetica)"

#: ../lib/keyboard.pm:206
#, c-format
msgid ""
"_: keyboard\n"
"Bulgarian (BDS)"
msgstr "Bulgara (BDS)"

#: ../lib/keyboard.pm:207
#, c-format
msgid ""
"_: keyboard\n"
"Brazilian (ABNT-2)"
msgstr "Brasiliana (ABNT-2)"

#: ../lib/keyboard.pm:208
#, c-format
msgid ""
"_: keyboard\n"
"Bosnian"
msgstr "Bosniaca"

#: ../lib/keyboard.pm:209
#, c-format
msgid ""
"_: keyboard\n"
"Dzongkha/Tibetan"
msgstr "Dzongkha/Tibetana"

#: ../lib/keyboard.pm:210
#, c-format
msgid ""
"_: keyboard\n"
"Belarusian"
msgstr "Bielorussa"

#: ../lib/keyboard.pm:211
#, c-format
msgid ""
"_: keyboard\n"
"Swiss (German layout)"
msgstr "Svizzera (mappa tedesca)"

#: ../lib/keyboard.pm:212
#, c-format
msgid ""
"_: keyboard\n"
"Swiss (French layout)"
msgstr "Svizzera (mappa francese)"

#: ../lib/keyboard.pm:214
#, c-format
msgid ""
"_: keyboard\n"
"Cherokee syllabics"
msgstr "Cherokee sillabica"

#: ../lib/keyboard.pm:216
#, c-format
msgid ""
"_: keyboard\n"
"Czech (QWERTY)"
msgstr "Ceca (QWERTY)"

#: ../lib/keyboard.pm:218
#, c-format
msgid ""
"_: keyboard\n"
"German (no dead keys)"
msgstr "Tedesca (senza tasti morti)"

#: ../lib/keyboard.pm:219
#, c-format
msgid ""
"_: keyboard\n"
"Devanagari"
msgstr "Devanagari"

#: ../lib/keyboard.pm:220
#, c-format
msgid ""
"_: keyboard\n"
"Danish"
msgstr "Danese"

#: ../lib/keyboard.pm:221
#, c-format
msgid ""
"_: keyboard\n"
"Dvorak (US)"
msgstr "Dvorak (US)"

#: ../lib/keyboard.pm:222
#, c-format
msgid ""
"_: keyboard\n"
"Dvorak (Esperanto)"
msgstr "Dvorak (Esperanto)"

#: ../lib/keyboard.pm:223
#, c-format
msgid ""
"_: keyboard\n"
"Dvorak (French)"
msgstr "Dvorak (Francese)"

#: ../lib/keyboard.pm:224
#, c-format
msgid ""
"_: keyboard\n"
"Dvorak (UK)"
msgstr "Dvorak (UK)"

#: ../lib/keyboard.pm:225
#, c-format
msgid ""
"_: keyboard\n"
"Dvorak (Norwegian)"
msgstr "Dvorak (Norvegese)"

#: ../lib/keyboard.pm:226
#, c-format
msgid ""
"_: keyboard\n"
"Dvorak (Polish)"
msgstr "Dvorak (Polacco)"

#: ../lib/keyboard.pm:227
#, c-format
msgid ""
"_: keyboard\n"
"Dvorak (Swedish)"
msgstr "Dvorak (Svedese)"

#: ../lib/keyboard.pm:228
#, c-format
msgid ""
"_: keyboard\n"
"Estonian"
msgstr "Estone"

#: ../lib/keyboard.pm:231
#, c-format
msgid ""
"_: keyboard\n"
"Faroese"
msgstr "Feringia"

#: ../lib/keyboard.pm:234
#, c-format
msgid ""
"_: keyboard\n"
"Georgian (\"Russian\" layout)"
msgstr "Georgiana (mappa \"Russa\")"

#: ../lib/keyboard.pm:235
#, c-format
msgid ""
"_: keyboard\n"
"Georgian (\"Latin\" layout)"
msgstr "Georgiana (mappa \"Latina\")"

#: ../lib/keyboard.pm:236
#, c-format
msgid ""
"_: keyboard\n"
"Greek"
msgstr "Greca"

#: ../lib/keyboard.pm:237
#, c-format
msgid ""
"_: keyboard\n"
"Greek (polytonic)"
msgstr "Greca (politonico)"

#: ../lib/keyboard.pm:238
#, c-format
msgid ""
"_: keyboard\n"
"Gujarati"
msgstr "Gujarati"

#: ../lib/keyboard.pm:239
#, c-format
msgid ""
"_: keyboard\n"
"Gurmukhi"
msgstr "Gurmukhi"

#: ../lib/keyboard.pm:240
#, c-format
msgid ""
"_: keyboard\n"
"Croatian"
msgstr "Croata"

#: ../lib/keyboard.pm:241
#, c-format
msgid ""
"_: keyboard\n"
"Hungarian"
msgstr "Ungherese"

#: ../lib/keyboard.pm:242
#, c-format
msgid ""
"_: keyboard\n"
"Irish"
msgstr "Irlandese"

#: ../lib/keyboard.pm:243
#, c-format
msgid ""
"_: keyboard\n"
"Inuktitut"
msgstr "Inuktitut"

#: ../lib/keyboard.pm:244
#, c-format
msgid ""
"_: keyboard\n"
"Israeli"
msgstr "Israeliana"

#: ../lib/keyboard.pm:245
#, c-format
msgid ""
"_: keyboard\n"
"Israeli (phonetic)"
msgstr "Israeliana (fonetica)"

#: ../lib/keyboard.pm:246
#, c-format
msgid ""
"_: keyboard\n"
"Iranian"
msgstr "Iraniana"

#: ../lib/keyboard.pm:247
#, c-format
msgid ""
"_: keyboard\n"
"Icelandic"
msgstr "Islandese"

#: ../lib/keyboard.pm:248
#, c-format
msgid ""
"_: keyboard\n"
"Italian"
msgstr "Italiana"

#: ../lib/keyboard.pm:252
#, c-format
msgid ""
"_: keyboard\n"
"Japanese 106 keys"
msgstr "Giapponese 106 tasti"

#: ../lib/keyboard.pm:253
#, c-format
msgid ""
"_: keyboard\n"
"Kannada"
msgstr "Kannada"

#: ../lib/keyboard.pm:254
#, c-format
msgid ""
"_: keyboard\n"
"Kyrgyz"
msgstr "Kirghisa"

#: ../lib/keyboard.pm:257
#, c-format
msgid ""
"_: keyboard\n"
"Korean"
msgstr "Coreana"

#: ../lib/keyboard.pm:259
#, c-format
msgid ""
"_: keyboard\n"
"Kurdish (arabic script)"
msgstr "Curda (grafia araba)"

#: ../lib/keyboard.pm:260
#, c-format
msgid ""
"_: keyboard\n"
"Latin American"
msgstr "Latino americana"

#: ../lib/keyboard.pm:262
#, c-format
msgid ""
"_: keyboard\n"
"Laotian"
msgstr "Laotiana"

#: ../lib/keyboard.pm:263
#, c-format
msgid ""
"_: keyboard\n"
"Lithuanian AZERTY (old)"
msgstr "Lituana AZERTY (vecchia)"

#: ../lib/keyboard.pm:265
#, c-format
msgid ""
"_: keyboard\n"
"Lithuanian AZERTY (new)"
msgstr "Lituana AZERTY (nuova)"

#: ../lib/keyboard.pm:266
#, c-format
msgid ""
"_: keyboard\n"
"Lithuanian \"number row\" QWERTY"
msgstr "Lituana \"riga numeri\" QWERTY"

#: ../lib/keyboard.pm:267
#, c-format
msgid ""
"_: keyboard\n"
"Lithuanian \"phonetic\" QWERTY"
msgstr "Lituana \"fonetica\" QWERTY"

#: ../lib/keyboard.pm:268
#, c-format
msgid ""
"_: keyboard\n"
"Latvian"
msgstr "Lettone"

#: ../lib/keyboard.pm:269
#, c-format
msgid ""
"_: keyboard\n"
"Malayalam"
msgstr "Malayalam"

#: ../lib/keyboard.pm:270
#, c-format
msgid ""
"_: keyboard\n"
"Maori"
msgstr ""
"_: tastiera\n"
"Maori"

#: ../lib/keyboard.pm:271
#, c-format
msgid ""
"_: keyboard\n"
"Macedonian"
msgstr "Macedone"

#: ../lib/keyboard.pm:272
#, c-format
msgid ""
"_: keyboard\n"
"Myanmar (Burmese)"
msgstr "Myanmar (Burmese)"

#: ../lib/keyboard.pm:273
#, c-format
msgid ""
"_: keyboard\n"
"Mongolian (cyrillic)"
msgstr "Mongola (cirillica)"

#: ../lib/keyboard.pm:274
#, c-format
msgid ""
"_: keyboard\n"
"Maltese (UK)"
msgstr "Maltese (UK)"

#: ../lib/keyboard.pm:275
#, c-format
msgid ""
"_: keyboard\n"
"Maltese (US)"
msgstr "Maltese (US)"

#: ../lib/keyboard.pm:276
#, c-format
msgid ""
"_: keyboard\n"
"Nigerian"
msgstr ""
"_: tastiera\n"
"Nigeriana"

#: ../lib/keyboard.pm:277
#, c-format
msgid ""
"_: keyboard\n"
"Dutch"
msgstr "Olandese"

#: ../lib/keyboard.pm:279
#, c-format
msgid ""
"_: keyboard\n"
"Oriya"
msgstr "Oriya"

#: ../lib/keyboard.pm:280
#, c-format
msgid ""
"_: keyboard\n"
"Polish (qwerty layout)"
msgstr "Polacca (mappa qwerty)"

#: ../lib/keyboard.pm:281
#, c-format
msgid ""
"_: keyboard\n"
"Polish (qwertz layout)"
msgstr "Polacca (mappa qwertz)"

#: ../lib/keyboard.pm:283
#, c-format
msgid ""
"_: keyboard\n"
"Pashto"
msgstr "Pashto"

#: ../lib/keyboard.pm:284
#, c-format
msgid ""
"_: keyboard\n"
"Portuguese"
msgstr "Portoghese"

#: ../lib/keyboard.pm:285
#, c-format
msgid ""
"_: keyboard\n"
"Canadian (Quebec)"
msgstr "Canadese (Quebec)"

#: ../lib/keyboard.pm:286
#, c-format
msgid ""
"_: keyboard\n"
"Romanian (qwertz)"
msgstr "Romena (qwertz)"

#: ../lib/keyboard.pm:287
#, c-format
msgid ""
"_: keyboard\n"
"Romanian (qwerty)"
msgstr "Romena (qwerty)"

#: ../lib/keyboard.pm:289
#, c-format
msgid ""
"_: keyboard\n"
"Russian (phonetic)"
msgstr "Russa (fonetica)"

#: ../lib/keyboard.pm:291
#, c-format
msgid ""
"_: keyboard\n"
"Slovenian"
msgstr "Slovena"

#: ../lib/keyboard.pm:293
#, c-format
msgid ""
"_: keyboard\n"
"Sinhala"
msgstr "Sinhala"

#: ../lib/keyboard.pm:294
#, c-format
msgid ""
"_: keyboard\n"
"Slovakian (QWERTZ)"
msgstr "Slovacca (QWERTZ)"

#: ../lib/keyboard.pm:295
#, c-format
msgid ""
"_: keyboard\n"
"Slovakian (QWERTY)"
msgstr "Slovacca (QWERTY)"

#: ../lib/keyboard.pm:296
#, c-format
msgid ""
"_: keyboard\n"
"Saami (norwegian)"
msgstr "Saami (norvegese)"

#: ../lib/keyboard.pm:297
#, c-format
msgid ""
"_: keyboard\n"
"Saami (swedish/finnish)"
msgstr "Saami (svedese/finlandese)"

#: ../lib/keyboard.pm:299
#, c-format
msgid ""
"_: keyboard\n"
"Sindhi"
msgstr "Sindhi"

#: ../lib/keyboard.pm:301
#, c-format
msgid ""
"_: keyboard\n"
"Serbian (cyrillic)"
msgstr "Serba (cirillica)"

#: ../lib/keyboard.pm:302
#, c-format
msgid ""
"_: keyboard\n"
"Syriac"
msgstr "Siriana"

#: ../lib/keyboard.pm:303
#, c-format
msgid ""
"_: keyboard\n"
"Syriac (phonetic)"
msgstr "Siriana (fonetica)"

#: ../lib/keyboard.pm:304
#, c-format
msgid ""
"_: keyboard\n"
"Telugu"
msgstr "Telugu"

#: ../lib/keyboard.pm:306
#, c-format
msgid ""
"_: keyboard\n"
"Tamil (ISCII-layout)"
msgstr "Tamil (mappa ISCII)"

#: ../lib/keyboard.pm:307
#, c-format
msgid ""
"_: keyboard\n"
"Tamil (Typewriter-layout)"
msgstr "Tamil (mappa macchina da scrivere)"

#: ../lib/keyboard.pm:308
#, c-format
msgid ""
"_: keyboard\n"
"Thai (Kedmanee)"
msgstr "Thai (Kedmanee)"

#: ../lib/keyboard.pm:309
#, c-format
msgid ""
"_: keyboard\n"
"Thai (TIS-820)"
msgstr "Thai (TIS-820)"

#: ../lib/keyboard.pm:311
#, c-format
msgid ""
"_: keyboard\n"
"Thai (Pattachote)"
msgstr "Thai (Pattachote)"

#: ../lib/keyboard.pm:313
#, c-format
msgid ""
"_: keyboard\n"
"Tifinagh (moroccan layout) (+latin/arabic)"
msgstr "Tifinagh (tastiera marocchina) (+latina/araba)"

#: ../lib/keyboard.pm:314
#, c-format
msgid ""
"_: keyboard\n"
"Tifinagh (phonetic) (+latin/arabic)"
msgstr "Tifinagh (fonetica) (+latina/araba)"

#: ../lib/keyboard.pm:316
#, c-format
msgid ""
"_: keyboard\n"
"Tajik"
msgstr "Tagica"

#: ../lib/keyboard.pm:318
#, c-format
msgid ""
"_: keyboard\n"
"Turkmen"
msgstr "Turcomanna"

#: ../lib/keyboard.pm:319
#, c-format
msgid ""
"_: keyboard\n"
"Turkish (traditional \"F\" model)"
msgstr "Turca (modello \"F\" tradizionale)"

#: ../lib/keyboard.pm:320
#, c-format
msgid ""
"_: keyboard\n"
"Turkish (modern \"Q\" model)"
msgstr "Turca (modello \"Q\" moderno)"

#: ../lib/keyboard.pm:322
#, c-format
msgid ""
"_: keyboard\n"
"Ukrainian"
msgstr "Ucraina"

#: ../lib/keyboard.pm:324
#, c-format
msgid ""
"_: keyboard\n"
"Urdu keyboard"
msgstr "Tastiera Urdu"

#: ../lib/keyboard.pm:326
#, c-format
msgid "US keyboard (international)"
msgstr "Tastiera US (internazionale)"

#: ../lib/keyboard.pm:327
#, c-format
msgid "ISO9995-3 (US keyboard with 3 levels per key)"
msgstr "ISO9995-3 (tastiera USA con 3 livelli per tasto)"

#: ../lib/keyboard.pm:328
#, c-format
msgid ""
"_: keyboard\n"
"Uzbek (cyrillic)"
msgstr "Uzbeka (cirillico)"

#: ../lib/keyboard.pm:330
#, c-format
msgid ""
"_: keyboard\n"
"Vietnamese \"numeric row\" QWERTY"
msgstr "Vietnamita \"riga numerica\" QWERTY"

#: ../lib/keyboard.pm:331
#, c-format
msgid ""
"_: keyboard\n"
"Yugoslavian (latin)"
msgstr "Jugoslava (latina)"

#: ../lib/keyboard.pm:338
#, c-format
msgid "Right Alt key"
msgstr "Tasto Alt di destra"

#: ../lib/keyboard.pm:339
#, c-format
msgid "Both Shift keys simultaneously"
msgstr "I due tasti Shift contemporaneamente"

#: ../lib/keyboard.pm:340
#, c-format
msgid "Control and Shift keys simultaneously"
msgstr "I tasti Ctrl e Shift contemporaneamente"

#: ../lib/keyboard.pm:341
#, c-format
msgid "CapsLock key"
msgstr "Il tasto CapsLock"

#: ../lib/keyboard.pm:342
#, c-format
msgid "Shift and CapsLock keys simultaneously"
msgstr "Tasti Shift e BloccaMaiusc. contemporaneamente"

#: ../lib/keyboard.pm:343
#, c-format
msgid "Ctrl and Alt keys simultaneously"
msgstr "Tasti Ctrl e Alt contemporaneamente"

#: ../lib/keyboard.pm:344
#, c-format
msgid "Alt and Shift keys simultaneously"
msgstr "I tasti Alt e Shift contemporaneamente"

#: ../lib/keyboard.pm:345
#, c-format
msgid "\"Menu\" key"
msgstr "Tasto \"Menu\""

#: ../lib/keyboard.pm:346
#, c-format
msgid "Left \"Windows\" key"
msgstr "Tasto \"Windows\" di sinistra"

#: ../lib/keyboard.pm:347
#, c-format
msgid "Right \"Windows\" key"
msgstr "Tasto \"Windows\" di destra"

#: ../lib/keyboard.pm:348
#, c-format
msgid "Both Control keys simultaneously"
msgstr "I due tasti Control contemporaneamente"

#: ../lib/keyboard.pm:349
#, c-format
msgid "Both Alt keys simultaneously"
msgstr "I due tasti Alt contemporaneamente"

#: ../lib/keyboard.pm:350
#, c-format
msgid "Left Shift key"
msgstr "Tasto Shift di sinistra"

#: ../lib/keyboard.pm:351
#, c-format
msgid "Right Shift key"
msgstr "Tasto Shift di destra"

#: ../lib/keyboard.pm:352
#, c-format
msgid "Left Alt key"
msgstr "Tasto Alt di sinistra"

#: ../lib/keyboard.pm:353
#, c-format
msgid "Left Control key"
msgstr "Tasto Control di sinistra"

#: ../lib/keyboard.pm:354
#, c-format
msgid "Right Control key"
msgstr "Tasto Control di destra"

#: ../lib/keyboard.pm:390
#, c-format
msgid ""
"Here you can choose the key or key combination that will \n"
"allow switching between the different keyboard layouts\n"
"(eg: latin and non latin)"
msgstr ""
"Qui si può scegliere il tasto, o la combinazione di tasti, che\n"
"permetterà di passare da una configurazione della tastiera\n"
"ad un'altra (ad es. da latin a non-latin)"

#: ../lib/keyboard.pm:394
#, c-format
msgid "Warning"
msgstr "Attenzione"

#: ../lib/keyboard.pm:395
#, c-format
msgid ""
"This setting will be activated after the installation.\n"
"During installation, you will need to use the Right Control\n"
"key to switch between the different keyboard layouts."
msgstr ""
"Questa funzione sarà attivata ad installazione finita.\n"
"Durante l'installazione dovrai usare il tasto Control di destra per passare "
"da una mappatura della tastiera all'altra."

#: ../lib/mouse.pm:25
#, c-format
msgid "Sun - Mouse"
msgstr "Mouse - Sun"

#: ../lib/mouse.pm:31
#, c-format
msgid "Standard"
msgstr "Normale"

#: ../lib/mouse.pm:32
#, c-format
msgid "Logitech MouseMan+"
msgstr "Logitech MouseMan+"

#: ../lib/mouse.pm:33
#, c-format
msgid "Generic PS2 Wheel Mouse"
msgstr "Mouse PS2 generico con rotellina"

#: ../lib/mouse.pm:34
#, c-format
msgid "GlidePoint"
msgstr "GlidePoint"

#: ../lib/mouse.pm:35
#, c-format
msgid "Automatic"
msgstr "IP automatico"

#: ../lib/mouse.pm:37 ../lib/mouse.pm:71
#, c-format
msgid "Kensington Thinking Mouse"
msgstr "Kensington Thinking Mouse"

#: ../lib/mouse.pm:38 ../lib/mouse.pm:66
#, c-format
msgid "Genius NetMouse"
msgstr "Genius NetMouse"

#: ../lib/mouse.pm:39
#, c-format
msgid "Genius NetScroll"
msgstr "Genius NetScroll"

#: ../lib/mouse.pm:40 ../lib/mouse.pm:50
#, c-format
msgid "Microsoft Explorer"
msgstr "Microsoft Explorer"

#: ../lib/mouse.pm:45 ../lib/mouse.pm:77
#, c-format
msgid "1 button"
msgstr "1 pulsante"

#: ../lib/mouse.pm:46 ../lib/mouse.pm:55
#, c-format
msgid "Generic 2 Button Mouse"
msgstr "Mouse generico a 2 Pulsanti"

#: ../lib/mouse.pm:48 ../lib/mouse.pm:57
#, c-format
msgid "Generic 3 Button Mouse with Wheel emulation"
msgstr "Mouse generico a 3 pulsanti con emulazione rotellina"

#: ../lib/mouse.pm:49
#, c-format
msgid "Wheel"
msgstr "Rotellina"

#: ../lib/mouse.pm:53
#, c-format
msgid "serial"
msgstr "seriale"

#: ../lib/mouse.pm:56
#, c-format
msgid "Generic 3 Button Mouse"
msgstr "Mouse generico a 3 pulsanti"

#: ../lib/mouse.pm:58
#, c-format
msgid "Microsoft IntelliMouse"
msgstr "Microsoft IntelliMouse"

#: ../lib/mouse.pm:59
#, c-format
msgid "Logitech MouseMan"
msgstr "Logitech MouseMan"

#: ../lib/mouse.pm:60
#, c-format
msgid "Logitech MouseMan with Wheel emulation"
msgstr "Logitech MouseMan con emulazione rotellina"

#: ../lib/mouse.pm:61
#, c-format
msgid "Mouse Systems"
msgstr "Mouse Systems"

#: ../lib/mouse.pm:63
#, c-format
msgid "Logitech CC Series"
msgstr "Logitech serie CC"

#: ../lib/mouse.pm:64
#, c-format
msgid "Logitech CC Series with Wheel emulation"
msgstr "Logitech serie CC con emulazione rotellina"

#: ../lib/mouse.pm:65
#, c-format
msgid "Logitech MouseMan+/FirstMouse+"
msgstr "Logitech MouseMan+/FirstMouse+"

#: ../lib/mouse.pm:67
#, c-format
msgid "MM Series"
msgstr "Serie MM"

#: ../lib/mouse.pm:68
#, c-format
msgid "MM HitTablet"
msgstr "MM HitTablet"

#: ../lib/mouse.pm:69
#, c-format
msgid "Logitech Mouse (serial, old C7 type)"
msgstr "Mouse Logitech (seriale, vecchio tipo C7)"

#: ../lib/mouse.pm:70
#, c-format
msgid "Logitech Mouse (serial, old C7 type) with Wheel emulation"
msgstr "Mouse Logitech (seriale, vecchio tipo C7) con emulazione rotellina"

#: ../lib/mouse.pm:72
#, c-format
msgid "Kensington Thinking Mouse with Wheel emulation"
msgstr "Kensington Thinking Mouse con emulazione rotellina"

#: ../lib/mouse.pm:75
#, c-format
msgid "busmouse"
msgstr "busmouse"

#: ../lib/mouse.pm:78
#, c-format
msgid "2 buttons"
msgstr "2 pulsanti"

#: ../lib/mouse.pm:79
#, c-format
msgid "3 buttons"
msgstr "3 pulsanti"

#: ../lib/mouse.pm:80
#, c-format
msgid "3 buttons with Wheel emulation"
msgstr "3 pulsanti con emulazione rotellina"

#: ../lib/mouse.pm:83
#, c-format
msgid "Universal"
msgstr "Universale"

#: ../lib/mouse.pm:85
#, c-format
msgid "Any PS/2 & USB mice"
msgstr "Qualsiasi mouse PS/2 o USB"

#: ../lib/mouse.pm:86
#, c-format
msgid "Microsoft Xbox Controller S"
msgstr "Controller S per Microsoft Xbox"

#: ../lib/mouse.pm:89
#, c-format
msgid "none"
msgstr "nessuno"

#: ../lib/mouse.pm:91
#, c-format
msgid "No mouse"
msgstr "Nessun mouse"

#: ../lib/mouse.pm:484
#, c-format
msgid "Testing the mouse"
msgstr "Prova del mouse"

#: ../lib/mouse.pm:516
#, c-format
msgid "Please choose your type of mouse."
msgstr "Scegliere il tipo di mouse."

#: ../lib/mouse.pm:517
#, c-format
msgid "Mouse choice"
msgstr "Scelta del mouse"

#: ../lib/mouse.pm:530
#, c-format
msgid "Emulate third button?"
msgstr "Emulare il terzo tasto?"

#: ../lib/mouse.pm:534
#, c-format
msgid "Mouse Port"
msgstr "Porta del mouse"

#: ../lib/mouse.pm:535
#, c-format
msgid "Please choose which serial port your mouse is connected to."
msgstr "Per favore indica la porta seriale a cui è connesso il mouse."

#: ../lib/mouse.pm:544
#, c-format
msgid "Buttons emulation"
msgstr "Emulazione dei pulsanti"

#: ../lib/mouse.pm:546
#, c-format
msgid "Button 2 Emulation"
msgstr "Emulazione 2 pulsanti"

#: ../lib/mouse.pm:547
#, c-format
msgid "Button 3 Emulation"
msgstr "Emulazione 3 pulsanti"

#: ../lib/mouse.pm:598
#, c-format
msgid "Please test the mouse"
msgstr "Puoi provare il mouse"

#: ../lib/mouse.pm:600
#, c-format
msgid "To activate the mouse,"
msgstr "Per attivare il mouse,"

#: ../lib/mouse.pm:601
#, c-format
msgid "MOVE YOUR WHEEL!"
msgstr "MUOVI LA ROTELLINA!"

#: ../tools/XFdrake:71
#, c-format
msgid "You need to reboot for changes to take effect"
msgstr "Serve un riavvio per rendere effettive le modifiche"

#: ../tools/keyboarddrake:32
#, c-format
msgid "Keyboard"
msgstr "Tastiera"

#: ../tools/keyboarddrake:33
#, c-format
msgid "Please, choose your keyboard layout."
msgstr "Indica la mappatura della tastiera."

#: ../tools/keyboarddrake:34
#, c-format
msgid "Keyboard layout"
msgstr "Mappatura della tastiera"

#: ../tools/keyboarddrake:42
#, c-format
msgid "Keyboard type"
msgstr "Tipo di tastiera"

#: ../tools/keyboarddrake:54
#, c-format
msgid "Do you want the BackSpace to return Delete in console?"
msgstr "Vuoi che in console il tasto BackSpace funzioni come Canc?"

#: ../tools/mousedrake:44
#, c-format
msgid "Mouse test"
msgstr "Prova del mouse"

#: ../tools/mousedrake:47
#, c-format
msgid "Please test your mouse:"
msgstr "Per favore prova il mouse:"

> 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547
/* -*- mode: C; mode: fold; -*- */
/* slang.c  --- guts of S-Lang interpreter */
/* Copyright (c) 1992, 1999, 2001 John E. Davis
 * This file is part of the S-Lang library.
 *
 * You may distribute under the terms of either the GNU General Public
 * License or the Perl Artistic License.
 */

#include "slinclud.h"

#if SLANG_HAS_FLOAT
# include <math.h>
#endif

#include "slang.h"
#include "_slang.h"

#define USE_COMBINED_BYTECODES	0

struct _SLBlock_Type;

typedef struct
{
   struct _SLBlock_Type *body;
   unsigned int num_refs;
}
_SLBlock_Header_Type;

typedef struct
{
   char *name;
   SLang_Name_Type *next;
   char name_type;

   union
     {
	_SLBlock_Header_Type *header;    /* body of function */
	char *autoload_filename;
     }
   v;
#if _SLANG_HAS_DEBUG_CODE
   char *file;
#endif
#define SLANG_MAX_LOCAL_VARIABLES 254
#define AUTOLOAD_NUM_LOCALS (SLANG_MAX_LOCAL_VARIABLES + 1)
   unsigned char nlocals;	       /* number of local variables */
   unsigned char nargs;		       /* number of arguments */
}
_SLang_Function_Type;

typedef struct
{
   char *name;
   SLang_Name_Type *next;
   char name_type;

   SLang_Object_Type obj;
}
SLang_Global_Var_Type;

typedef struct
{
   char *name;
   SLang_Name_Type *next;
   char name_type;

   int local_var_number;
}
SLang_Local_Var_Type;

typedef struct _SLBlock_Type
{
   unsigned char bc_main_type;
   unsigned char bc_sub_type;
   union
     {
	struct _SLBlock_Type *blk;
	int i_blk;

	SLang_Name_Type *nt_blk;
	SLang_App_Unary_Type *nt_unary_blk;
	SLang_Intrin_Var_Type *nt_ivar_blk;
	SLang_Intrin_Fun_Type *nt_ifun_blk;
	SLang_Global_Var_Type *nt_gvar_blk;
	SLang_IConstant_Type *iconst_blk;
	SLang_DConstant_Type *dconst_blk;
	_SLang_Function_Type *nt_fun_blk;

	VOID_STAR ptr_blk;
	char *s_blk;
	SLang_BString_Type *bs_blk;

#if SLANG_HAS_FLOAT
	double *double_blk;		       /*literal double is a pointer */
#endif
	float float_blk;
	long l_blk;
	struct _SLang_Struct_Type *struct_blk;
	int (*call_function)(void);
     }
   b;
}
SLBlock_Type;

/* Debugging and tracing variables */

void (*SLang_Enter_Function)(char *) = NULL;
void (*SLang_Exit_Function)(char *) = NULL;
/* If non null, these call C functions before and after a slang function. */

int _SLang_Trace = 0;
/* If _SLang_Trace = -1, do not trace intrinsics */
static int Trace_Mode = 0;

static char *Trace_Function;	       /* function to be traced */
int SLang_Traceback = 0;
/* non zero means do traceback.  If less than 0, do not show local variables */

/* These variables handle _NARGS processing by the parser */
int SLang_Num_Function_Args;
static int *Num_Args_Stack;
static unsigned int Recursion_Depth;
static SLang_Object_Type *Frame_Pointer;
static int Next_Function_Num_Args;
static unsigned int Frame_Pointer_Depth;
static unsigned int *Frame_Pointer_Stack;

static int Lang_Break_Condition = 0;
/* true if any one below is true.  This keeps us from testing 3 variables.
 * I know this can be perfomed with a bitmapped variable, but...
 */
static int Lang_Break = 0;
static int Lang_Return = 0;
/* static int Lang_Continue = 0; */

SLang_Object_Type *_SLRun_Stack;
SLang_Object_Type *_SLStack_Pointer;
static SLang_Object_Type *_SLStack_Pointer_Max;

/* Might want to increase this. */
static SLang_Object_Type Local_Variable_Stack[SLANG_MAX_LOCAL_STACK];
static SLang_Object_Type *Local_Variable_Frame = Local_Variable_Stack;

static void free_function_header (_SLBlock_Header_Type *);

void (*SLang_Dump_Routine)(char *);

static void call_dump_routine (char *fmt, ...)
{
   char buf[1024];
   va_list ap;

   va_start (ap, fmt);
   if (SLang_Dump_Routine != NULL)
     {
	(void) _SLvsnprintf (buf, sizeof (buf), fmt, ap);
	(*SLang_Dump_Routine) (buf);
     }
   else
     {
	vfprintf (stderr, fmt, ap);
	fflush (stderr);
     }
   va_end (ap);
}

static void do_traceback (char *, unsigned int, char *);
static int init_interpreter (void);

/*{{{ push/pop/etc stack manipulation functions */

/* This routine is assumed to work even in the presence of a SLang_Error. */
_INLINE_
int SLang_pop (SLang_Object_Type *x)
{
   register SLang_Object_Type *y;

   y = _SLStack_Pointer;
   if (y == _SLRun_Stack)
     {
	if (SLang_Error == 0) SLang_Error = SL_STACK_UNDERFLOW;
	x->data_type = 0;
	return -1;
     }
   y--;
   *x = *y;

   _SLStack_Pointer = y;
   return 0;
}

static int pop_ctrl_integer (int *i)
{
   int type;
   SLang_Class_Type *cl;
#if _SLANG_OPTIMIZE_FOR_SPEED
   register SLang_Object_Type *y;

   /* Most of the time, either an integer or a char will be on the stack.
    * Optimize these cases.
    */
   y = _SLStack_Pointer;
   if (y == _SLRun_Stack)
     {
	if (SLang_Error == 0) SLang_Error = SL_STACK_UNDERFLOW;
	return -1;
     }
   y--;
   
   type = y->data_type;
   if (type == SLANG_INT_TYPE)
     {
	_SLStack_Pointer = y;   
	*i = y->v.int_val;
	return 0;
     }
   if (type == SLANG_CHAR_TYPE)
     {
	_SLStack_Pointer = y;   
	*i = y->v.char_val;
	return 0;
     }
#else
   if (-1 == (type = SLang_peek_at_stack ()))
     return -1;
#endif

   cl = _SLclass_get_class ((unsigned char) type);
   if (cl->cl_to_bool == NULL)
     {
	SLang_verror (SL_TYPE_MISMATCH,
		      "%s cannot be used in a boolean context",
		      cl->cl_name);
	return -1;
     }
   return cl->cl_to_bool ((unsigned char) type, i);
}

_INLINE_
int SLang_peek_at_stack (void)
{
   if (_SLStack_Pointer == _SLRun_Stack)
     {
	if (SLang_Error == 0)
	  SLang_Error = SL_STACK_UNDERFLOW;
	return -1;
     }

   return (_SLStack_Pointer - 1)->data_type;
}

int SLang_peek_at_stack1 (void)
{
   int type;

   type = SLang_peek_at_stack ();
   if (type == SLANG_ARRAY_TYPE)
     type = (_SLStack_Pointer - 1)->v.array_val->data_type;

   return type;
}

_INLINE_
void SLang_free_object (SLang_Object_Type *obj)
{
   unsigned char data_type;
   SLang_Class_Type *cl;

   if (obj == NULL) return;
   data_type = obj->data_type;
#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type [data_type])
     return;
   if (data_type == SLANG_STRING_TYPE)
     {
	SLang_free_slstring (obj->v.s_val);
	return;
     }
#endif
   cl = _SLclass_get_class (data_type);
#if !_SLANG_OPTIMIZE_FOR_SPEED
   if (cl->cl_class_type != SLANG_CLASS_TYPE_SCALAR)
#endif
     (*cl->cl_destroy) (data_type, (VOID_STAR) &obj->v);
}

_INLINE_
int SLang_push (SLang_Object_Type *x)
{
   register SLang_Object_Type *y;
   y = _SLStack_Pointer;

   /* if there is a SLang_Error, probably not much harm will be done
    if it is ignored here */
   /* if (SLang_Error) return; */

   /* flag it now */
   if (y >= _SLStack_Pointer_Max)
     {
	if (!SLang_Error) SLang_Error = SL_STACK_OVERFLOW;
	return -1;
     }

   *y = *x;
   _SLStack_Pointer = y + 1;
   return 0;
}

/* _INLINE_ */
int SLclass_push_ptr_obj (unsigned char type, VOID_STAR pval)
{
   register SLang_Object_Type *y;
   y = _SLStack_Pointer;

   if (y >= _SLStack_Pointer_Max)
     {
	if (!SLang_Error) SLang_Error = SL_STACK_OVERFLOW;
	return -1;
     }

   y->data_type = type;
   y->v.ptr_val = pval;

   _SLStack_Pointer = y + 1;
   return 0;
}

_INLINE_
int SLclass_push_int_obj (unsigned char type, int x)
{
   register SLang_Object_Type *y;
   y = _SLStack_Pointer;

   if (y >= _SLStack_Pointer_Max)
     {
	if (!SLang_Error) SLang_Error = SL_STACK_OVERFLOW;
	return -1;
     }

   y->data_type = type;
   y->v.int_val = x;

   _SLStack_Pointer = y + 1;
   return 0;
}

_INLINE_
int _SLang_pop_object_of_type (unsigned char type, SLang_Object_Type *obj,
			       int allow_arrays)
{
   register SLang_Object_Type *y;

   y = _SLStack_Pointer;
   if (y == _SLRun_Stack)
     return SLang_pop (obj);
   y--;
   if (y->data_type != type)
     {
#if _SLANG_OPTIMIZE_FOR_SPEED
	/* This is an implicit typecast.  We do not want to typecast
	 * floats to ints implicitly.  
	 */
	if (_SLarith_Is_Arith_Type [type]
	    && _SLarith_Is_Arith_Type [y->data_type]
	    && (_SLarith_Is_Arith_Type [type] >= _SLarith_Is_Arith_Type[y->data_type]))
	  {
	     /* This should not fail */
	     (void) _SLarith_typecast (y->data_type, (VOID_STAR)&y->v, 1, 
				       type, (VOID_STAR)&obj->v);
	     obj->data_type = type;
	     _SLStack_Pointer = y;
	     return 0;
	  }
#endif
	
	if ((allow_arrays == 0)
	    || (y->data_type != SLANG_ARRAY_TYPE)
	    || (y->v.array_val->data_type != type))
	  if (-1 == SLclass_typecast (type, 1, 0))
	    return -1;
     }
   *obj = *y;
   _SLStack_Pointer = y;
   return 0;
}

/*  This function reverses the top n items on the stack and returns a
 *  an offset from the start of the stack to the last item.
 */
int SLreverse_stack (int n)
{
   SLang_Object_Type *otop, *obot, tmp;

   otop = _SLStack_Pointer;
   if ((n > otop - _SLRun_Stack) || (n < 0))
     {
	SLang_Error = SL_STACK_UNDERFLOW;
	return -1;
     }
   obot = otop - n;
   otop--;
   while (otop > obot)
     {
	tmp = *obot;
	*obot = *otop;
	*otop = tmp;
	otop--;
	obot++;
     }
   return (int) ((_SLStack_Pointer - n) - _SLRun_Stack);
}

_INLINE_
int SLroll_stack (int np)
{
   int n, i;
   SLang_Object_Type *otop, *obot, tmp;

   if ((n = abs(np)) <= 1) return 0;    /* identity */

   obot = otop = _SLStack_Pointer;
   i = n;
   while (i != 0)
     {
	if (obot <= _SLRun_Stack)
	  {
	     SLang_Error = SL_STACK_UNDERFLOW;
	     return -1;
	  }
	obot--;
	i--;
     }
   otop--;

   if (np > 0)
     {
	/* Put top on bottom and roll rest up. */
	tmp = *otop;
	while (otop > obot)
	  {
	     *otop = *(otop - 1);
	     otop--;
	  }
	*otop = tmp;
     }
   else
     {
	/* Put bottom on top and roll rest down. */
	tmp = *obot;
	while (obot < otop)
	  {
	     *obot = *(obot + 1);
	     obot++;
	  }
	*obot = tmp;
     }
   return 0;
}

int _SLstack_depth (void)
{
   return (int) (_SLStack_Pointer - _SLRun_Stack);
}

int SLdup_n (int n)
{
   SLang_Object_Type *bot, *top;

   if (n <= 0)
     return 0;
   
   top = _SLStack_Pointer;
   if (top < _SLRun_Stack + n)
     {
	if (SLang_Error == 0)
	  SLang_Error = SL_STACK_UNDERFLOW;
	return -1;
     }
   if (top + n > _SLStack_Pointer_Max)
     {
	if (SLang_Error == 0)
	  SLang_Error = SL_STACK_OVERFLOW;
	return -1;
     }
   bot = top - n;

   while (bot < top)
     {
	SLang_Class_Type *cl;
	unsigned char data_type = bot->data_type;

#if _SLANG_OPTIMIZE_FOR_SPEED
	if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type [data_type])
	  {
	     *_SLStack_Pointer++ = *bot++;
	     continue;
	  }
#endif
	cl = _SLclass_get_class (data_type);
	if (-1 == (*cl->cl_push) (data_type, (VOID_STAR) &bot->v))
	  return -1;
	bot++;
     }
   return 0;
}

/*}}}*/

/*{{{ inner interpreter and support functions */

_INLINE_
int _SL_increment_frame_pointer (void)
{
   if (Recursion_Depth >= SLANG_MAX_RECURSIVE_DEPTH)
     {
	SLang_verror (SL_STACK_OVERFLOW, "Num Args Stack Overflow");
	return -1;
     }
   Num_Args_Stack [Recursion_Depth] = SLang_Num_Function_Args;

   SLang_Num_Function_Args = Next_Function_Num_Args;
   Next_Function_Num_Args = 0;
   Recursion_Depth++;
   return 0;
}

_INLINE_
int _SL_decrement_frame_pointer (void)
{
   if (Recursion_Depth == 0)
     {
	SLang_verror (SL_STACK_UNDERFLOW, "Num Args Stack Underflow");
	return -1;
     }

   Recursion_Depth--;
   if (Recursion_Depth < SLANG_MAX_RECURSIVE_DEPTH)
     SLang_Num_Function_Args = Num_Args_Stack [Recursion_Depth];

   return 0;
}

_INLINE_
int SLang_start_arg_list (void)
{
   if (Frame_Pointer_Depth < SLANG_MAX_RECURSIVE_DEPTH)
     {
	Frame_Pointer_Stack [Frame_Pointer_Depth] = (unsigned int) (Frame_Pointer - _SLRun_Stack);
	Frame_Pointer = _SLStack_Pointer;
	Frame_Pointer_Depth++;
	Next_Function_Num_Args = 0;
	return 0;
     }

   SLang_verror (SL_STACK_OVERFLOW, "Frame Stack Overflow");
   return -1;
}

_INLINE_
int SLang_end_arg_list (void)
{
   if (Frame_Pointer_Depth == 0)
     {
	SLang_verror (SL_STACK_UNDERFLOW, "Frame Stack Underflow");
	return -1;
     }
   Frame_Pointer_Depth--;
   if (Frame_Pointer_Depth < SLANG_MAX_RECURSIVE_DEPTH)
     {
	Next_Function_Num_Args = (int) (_SLStack_Pointer - Frame_Pointer);
	Frame_Pointer = _SLRun_Stack + Frame_Pointer_Stack [Frame_Pointer_Depth];
     }
   return 0;
}

_INLINE_
static int do_bc_call_direct_frame (int (*f)(void))
{
   if ((0 == SLang_end_arg_list ())
       && (0 == _SL_increment_frame_pointer ()))
     {
	(void) (*f) ();
	_SL_decrement_frame_pointer ();
     }
   if (SLang_Error)
     return -1;
   return 0;
}

static int do_name_type_error (SLang_Name_Type *nt)
{
   char buf[256];
   if (nt != NULL)
     {
	(void) _SLsnprintf (buf, sizeof (buf), "(Error occurred processing %s)", nt->name);
	do_traceback (buf, 0, NULL);
     }
   return -1;
}

/* local and global variable assignments */

static int do_binary_ab (int op, SLang_Object_Type *obja, SLang_Object_Type *objb)
{
   SLang_Class_Type *a_cl, *b_cl, *c_cl;
   unsigned char b_data_type, a_data_type, c_data_type;
   int (*binary_fun) (int,
		      unsigned char, VOID_STAR, unsigned int,
		      unsigned char, VOID_STAR, unsigned int,
		      VOID_STAR);
   VOID_STAR pa;
   VOID_STAR pb;
   VOID_STAR pc;
   int ret;

   b_data_type = objb->data_type;
   a_data_type = obja->data_type;

#if _SLANG_OPTIMIZE_FOR_SPEED
   if (_SLarith_Is_Arith_Type[a_data_type]
       && _SLarith_Is_Arith_Type[b_data_type])
     {
	int status;
	status = _SLarith_bin_op (obja, objb, op);
	if (status != 1)
	  return status;
	/* drop and try it the hard way */
     }
#endif

   a_cl = _SLclass_get_class (a_data_type);
   if (a_data_type == b_data_type)
     b_cl = a_cl;
   else
     b_cl = _SLclass_get_class (b_data_type);

   if (NULL == (binary_fun = _SLclass_get_binary_fun (op, a_cl, b_cl, &c_cl, 1)))
     return -1;

   c_data_type = c_cl->cl_data_type;

#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type [a_data_type])
     pa = (VOID_STAR) &obja->v;
   else
#endif
     pa = _SLclass_get_ptr_to_value (a_cl, obja);

#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type [b_data_type])
     pb = (VOID_STAR) &objb->v;
   else
#endif
     pb = _SLclass_get_ptr_to_value (b_cl, objb);

   pc = c_cl->cl_transfer_buf;

   if (1 != (*binary_fun) (op,
			   a_data_type, pa, 1,
			   b_data_type, pb, 1,
			   pc))
     {
	SLang_verror (SL_NOT_IMPLEMENTED,
		      "Binary operation between %s and %s failed",
		      a_cl->cl_name, b_cl->cl_name);

	return -1;
     }

   /* apush will create a copy, so make sure we free after the push */
   ret = (*c_cl->cl_apush)(c_data_type, pc);
#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [c_data_type])
#endif
     (*c_cl->cl_adestroy)(c_data_type, pc);

   return ret;
}

_INLINE_
static void do_binary (int op)
{
   SLang_Object_Type obja, objb;

   if (SLang_pop (&objb)) return;
   if (0 == SLang_pop (&obja))
     {
	(void) do_binary_ab (op, &obja, &objb);
#if _SLANG_OPTIMIZE_FOR_SPEED
	if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [obja.data_type])
#endif
	  SLang_free_object (&obja);
     }
#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [objb.data_type])
#endif
     SLang_free_object (&objb);
}

static int do_unary_op (int op, SLang_Object_Type *obj, int unary_type)
{
   int (*f) (int, unsigned char, VOID_STAR, unsigned int, VOID_STAR);
   VOID_STAR pa;
   VOID_STAR pb;
   SLang_Class_Type *a_cl, *b_cl;
   unsigned char a_type, b_type;
   int ret;

   a_type = obj->data_type;
   a_cl = _SLclass_get_class (a_type);

   if (NULL == (f = _SLclass_get_unary_fun (op, a_cl, &b_cl, unary_type)))
     return -1;

   b_type = b_cl->cl_data_type;

#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type [a_type])
     pa = (VOID_STAR) &obj->v;
   else
#endif
     pa = _SLclass_get_ptr_to_value (a_cl, obj);

   pb = b_cl->cl_transfer_buf;

   if (1 != (*f) (op, a_type, pa, 1, pb))
     {
	SLang_verror (SL_NOT_IMPLEMENTED,
		      "Unary operation for %s failed", a_cl->cl_name);
	return -1;
     }

   ret = (*b_cl->cl_apush)(b_type, pb);
   /* cl_apush creates a copy, so make sure we call cl_adestroy */
#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [b_type])
#endif
     (*b_cl->cl_adestroy)(b_type, pb);

   return ret;
}

_INLINE_
static int do_unary (int op, int unary_type)
{
   SLang_Object_Type obj;
   int ret;

   if (-1 == SLang_pop (&obj)) return -1;
   ret = do_unary_op (op, &obj, unary_type);
#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [obj.data_type])
#endif
     SLang_free_object (&obj);
   return ret;
}

static int do_assignment_binary (int op, SLang_Object_Type *obja_ptr)
{
   SLang_Object_Type objb;
   int ret;

   if (SLang_pop (&objb))
     return -1;

   ret = do_binary_ab (op, obja_ptr, &objb);
#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [objb.data_type])
#endif
     SLang_free_object (&objb);
   return ret;
}

/* The order of these is assumed to match the binary operators
 * defined in slang.h
 */
static int
map_assignment_op_to_binary (unsigned char op_type, int *op, int *is_unary)
{
   *is_unary = 0;
   switch (op_type)
     {
      case _SLANG_BCST_PLUSEQS:
      case _SLANG_BCST_MINUSEQS:
      case _SLANG_BCST_TIMESEQS:
      case _SLANG_BCST_DIVEQS:
	*op = SLANG_PLUS + (op_type - _SLANG_BCST_PLUSEQS);
	break;

      case _SLANG_BCST_BOREQS:
	*op = SLANG_BOR;
	break;

      case _SLANG_BCST_BANDEQS:
	*op = SLANG_BAND;
	break;

      case _SLANG_BCST_POST_MINUSMINUS:
      case _SLANG_BCST_MINUSMINUS:
	*op = SLANG_MINUS;
	*is_unary = 1;
	break;

      case _SLANG_BCST_PLUSPLUS:
      case _SLANG_BCST_POST_PLUSPLUS:
	*op = SLANG_PLUS;
	*is_unary = 1;
	break;

      default:
	SLang_verror (SL_NOT_IMPLEMENTED, "Assignment operator not implemented");
	return -1;
     }
   return 0;
}

static int
perform_lvalue_operation (unsigned char op_type, SLang_Object_Type *obja_ptr)
{
   switch (op_type)
     {
      case _SLANG_BCST_ASSIGN:
	break;

	/* The order of these is assumed to match the binary operators
	 * defined in slang.h
	 */
      case _SLANG_BCST_PLUSEQS:
      case _SLANG_BCST_MINUSEQS:
      case _SLANG_BCST_TIMESEQS:
      case _SLANG_BCST_DIVEQS:
	if (-1 == do_assignment_binary (SLANG_PLUS + (op_type - _SLANG_BCST_PLUSEQS), obja_ptr))
	  return -1;
	break;

      case _SLANG_BCST_BOREQS:
	if (-1 == do_assignment_binary (SLANG_BOR, obja_ptr))
	  return -1;
	break;

      case _SLANG_BCST_BANDEQS:
	if (-1 == do_assignment_binary (SLANG_BAND, obja_ptr))
	  return -1;
	break;

      case _SLANG_BCST_PLUSPLUS:
      case _SLANG_BCST_POST_PLUSPLUS:
#if _SLANG_OPTIMIZE_FOR_SPEED
	if (obja_ptr->data_type == SLANG_INT_TYPE)
	  return SLclass_push_int_obj (SLANG_INT_TYPE, obja_ptr->v.int_val + 1);
#endif
	if (-1 == do_unary_op (SLANG_PLUSPLUS, obja_ptr, _SLANG_BC_UNARY))
	  return -1;
	break;

      case _SLANG_BCST_MINUSMINUS:
      case _SLANG_BCST_POST_MINUSMINUS:
#if _SLANG_OPTIMIZE_FOR_SPEED
	if (obja_ptr->data_type == SLANG_INT_TYPE)
	  return SLclass_push_int_obj (SLANG_INT_TYPE, obja_ptr->v.int_val - 1);
#endif
	if (-1 == do_unary_op (SLANG_MINUSMINUS, obja_ptr, _SLANG_BC_UNARY))
	  return -1;
	break;

      default:
	SLang_Error = SL_INTERNAL_ERROR;
	return -1;
     }
   return 0;
}

_INLINE_
static int
set_lvalue_obj (unsigned char op_type, SLang_Object_Type *obja_ptr)
{
   if (op_type != _SLANG_BCST_ASSIGN)
     {
	if (-1 == perform_lvalue_operation (op_type, obja_ptr))
	  return -1;
     }
#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [obja_ptr->data_type])
#endif
     SLang_free_object (obja_ptr);

   return SLang_pop(obja_ptr);
}

static int
set_struct_lvalue (SLBlock_Type *bc_blk)
{
   int type;
   SLang_Class_Type *cl;
   char *name;
   int op;

   if (-1 == (type = SLang_peek_at_stack ()))
     return -1;

   cl = _SLclass_get_class (type);
   if ((cl->cl_sput == NULL)
       || (cl->cl_sget == NULL))
     {
	SLang_verror (SL_NOT_IMPLEMENTED,
		      "%s does not support structure access",
		      cl->cl_name);
	SLdo_pop_n (2);		       /* object plus what was to be assigned */
	return -1;
     }
   name = bc_blk->b.s_blk;
   op = bc_blk->bc_sub_type;

   if (op != _SLANG_BCST_ASSIGN)
     {
	/* We have something like (A.x += b) or (A.x++).  In either case,
	 * we need A.x.
	 */
	SLang_Object_Type obj_A;
	SLang_Object_Type obj;

	if (-1 == SLang_pop (&obj_A))
	  return -1;

	if ((-1 == _SLpush_slang_obj (&obj_A))
	    || (-1 == cl->cl_sget ((unsigned char) type, name))
	    || (-1 == SLang_pop (&obj)))
	  {
	     SLang_free_object (&obj_A);
	     return -1;
	  }
	/* Now the value of A.x is in obj. */
	if (-1 == perform_lvalue_operation (op, &obj))
	  {
	     SLang_free_object (&obj);
	     SLang_free_object (&obj_A);
	     return -1;
	  }
	SLang_free_object (&obj);
	/* The result of the operation is now on the stack.
	 * Perform assignment */
	if (-1 == SLang_push (&obj_A))
	  {
	     SLang_free_object (&obj_A);
	     return -1;
	  }
     }

   return (*cl->cl_sput) ((unsigned char) type, name);
}

static int make_unit_object (SLang_Object_Type *a, SLang_Object_Type *u)
{
   unsigned char type;
   
   type = a->data_type;
   if (type == SLANG_ARRAY_TYPE)
     type = a->v.array_val->data_type;
   
   u->data_type = type;
   switch (type)
     {
      case SLANG_UCHAR_TYPE:
      case SLANG_CHAR_TYPE:
	u->v.char_val = 1;
	break;

      case SLANG_SHORT_TYPE:
      case SLANG_USHORT_TYPE:
	u->v.short_val = 1;
	break;

      case SLANG_LONG_TYPE:
      case SLANG_ULONG_TYPE:
	u->v.long_val = 1;
	break;

#if SLANG_HAS_FLOAT
      case SLANG_FLOAT_TYPE:
	u->v.float_val = 1;
	break;
	
      case SLANG_COMPLEX_TYPE:
	u->data_type = SLANG_DOUBLE_TYPE;
      case SLANG_DOUBLE_TYPE:
	u->v.double_val = 1;
	break;
#endif
      default:
	u->data_type = SLANG_INT_TYPE;
	u->v.int_val = 1;
     }
   return 0;
}


/* We want to convert 'A[i] op X' to 'A[i] = A[i] op X'.  The code that
 * has been generated is:  X __args i A __aput-op
 * where __aput-op represents this function.  We need to generate:
 * __args i A __eargs __aget X op __args i A __eargs __aput
 * Here, __eargs implies a call to do_bc_call_direct_frame with either
 * the aput or aget function.  In addition, __args represents a call to 
 * SLang_start_arg_list.  Of course, i represents a set of indices.
 * 
 * Note: If op is an unary operation (e.g., ++ or --), then X will not
 * b present an will have to be taken to be 1.
 * 
 * Implementation note: For efficiency, calls to setup the frame, start
 * arg list will be omitted and SLang_Num_Function_Args will be set.
 * This is ugly but the alternative is much less efficient rendering these
 * assignment operators useless.  So, the plan is to roll the stack to get X,
 * then duplicate the next N values, call __aget followed by op X, finally
 * calling __aput.  Hence, the sequence is:
 * 
 *     start:   X i .. j A 
 *      dupN:   X i .. j A i .. j A
 *    __aget:   X i .. j A Y
 *      roll:   i .. j A Y X
 *        op:   i .. j A Z
 *      roll:   Z i .. j A
 *    __aput:
 */
static int
set_array_lvalue (int op)
{
   SLang_Object_Type x, y;
   int num_args, is_unary;

   if (-1 == map_assignment_op_to_binary (op, &op, &is_unary))
     return -1;

   /* Grab the indices and the array.  Do not start a new frame. */
   if (-1 == SLang_end_arg_list ())
     return -1;
   num_args = Next_Function_Num_Args;
   Next_Function_Num_Args = 0;

   if (-1 == SLdup_n (num_args))
     return -1;

   SLang_Num_Function_Args = num_args;
   if (-1 == _SLarray_aget ())
     return -1;

   if (-1 == SLang_pop (&y))
     return -1;
   
   if (is_unary == 0)
     {
	if ((-1 == SLroll_stack (-(num_args + 1)))
	    || (-1 == SLang_pop (&x)))
	  {
	     SLang_free_object (&y);
	     return -1;
	  }
     }
   else if (-1 == make_unit_object (&y, &x))
     {
	SLang_free_object (&y);
	return -1;
     }
   
   if (-1 == do_binary_ab (op, &y, &x))
     {
	SLang_free_object (&y);
	SLang_free_object (&x);
	return -1;
     }
#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [y.data_type])
#endif
     SLang_free_object (&y);
   
#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [x.data_type])
#endif
     SLang_free_object (&x);

   if (-1 == SLroll_stack (num_args + 1))
     return -1;

   SLang_Num_Function_Args = num_args;
   return _SLarray_aput ();
}


static int
set_intrin_lvalue (SLBlock_Type *bc_blk)
{
   unsigned char op_type;
   SLang_Object_Type obja;
   SLang_Class_Type *cl;
   SLang_Intrin_Var_Type *ivar;
   VOID_STAR intrinsic_addr;
   unsigned char intrinsic_type;

   ivar = bc_blk->b.nt_ivar_blk;

   intrinsic_type = ivar->type;
   intrinsic_addr = ivar->addr;

   op_type = bc_blk->bc_sub_type;

   cl = _SLclass_get_class (intrinsic_type);

   if (op_type != _SLANG_BCST_ASSIGN)
     {
	/* We want to get the current value into obja.  This is the
	 * easiest way.
	 */
	if ((-1 == (*cl->cl_push) (intrinsic_type, intrinsic_addr))
	    || (-1 == SLang_pop (&obja)))
	  return -1;

	(void) perform_lvalue_operation (op_type, &obja);
	SLang_free_object (&obja);

	if (SLang_Error)
	  return -1;
     }

   return (*cl->cl_pop) (intrinsic_type, intrinsic_addr);
}

int _SLang_deref_assign (SLang_Ref_Type *ref)
{
   SLang_Object_Type *objp;
   SLang_Name_Type *nt;
   SLBlock_Type blk;

   if (ref->is_global == 0)
     {
	objp = ref->v.local_obj;
	if (objp > Local_Variable_Frame)
	  {
	     SLang_verror (SL_UNDEFINED_NAME, "Local variable reference is out of scope");
	     return -1;
	  }
	return set_lvalue_obj (_SLANG_BCST_ASSIGN, objp);
     }

   nt = ref->v.nt;
   switch (nt->name_type)
     {
      case SLANG_GVARIABLE:
      case SLANG_PVARIABLE:
	if (-1 == set_lvalue_obj (_SLANG_BCST_ASSIGN,
				  &((SLang_Global_Var_Type *)nt)->obj))
	  {
	     do_name_type_error (nt);
	     return -1;
	  }
	break;

      case SLANG_IVARIABLE:
	blk.b.nt_blk = nt;
	blk.bc_sub_type = _SLANG_BCST_ASSIGN;
	if (-1 == set_intrin_lvalue (&blk))
	  {
	     do_name_type_error (nt);
	     return -1;
	  }
	break;

      case SLANG_LVARIABLE:
	SLang_Error = SL_INTERNAL_ERROR;
	/* set_intrin_lvalue (&blk); */
	return -1;

      case SLANG_RVARIABLE:
      default:
	SLang_verror (SL_READONLY_ERROR, "deref assignment to %s not allowed", nt->name);
	return -1;
     }

   return 0;
}

static void set_deref_lvalue (SLBlock_Type *bc_blk)
{
   SLang_Object_Type *objp;
   SLang_Ref_Type *ref;

   switch (bc_blk->bc_sub_type)
     {
      case SLANG_LVARIABLE:
	objp =  (Local_Variable_Frame - bc_blk->b.i_blk);
	break;
      case SLANG_GVARIABLE:
      case SLANG_PVARIABLE:
	objp = &bc_blk->b.nt_gvar_blk->obj;
	break;
      default:
	SLang_Error = SL_INTERNAL_ERROR;
	return;
     }

   if (-1 == _SLpush_slang_obj (objp))
     return;

   if (-1 == SLang_pop_ref (&ref))
     return;
   (void) _SLang_deref_assign (ref);
   SLang_free_ref (ref);
}

static int push_struct_field (char *name)
{
   int type;
   SLang_Class_Type *cl;

   if (-1 == (type = SLang_peek_at_stack ()))
     return -1;

   cl = _SLclass_get_class ((unsigned char) type);
   if (cl->cl_sget == NULL)
     {
	SLang_verror (SL_NOT_IMPLEMENTED,
		      "%s does not permit structure access",
		      cl->cl_name);
	SLdo_pop_n (2);
	return -1;
     }

   return (*cl->cl_sget) ((unsigned char) type, name);
}

static void trace_dump (char *format, char *name, SLang_Object_Type *objs, int n, int dir)
{
   unsigned int len;
   char prefix [52];

   len = Trace_Mode - 1;
   if (len + 2 >= sizeof (prefix))
     len = sizeof (prefix) - 2;

   SLMEMSET (prefix, ' ', len);
   prefix[len] = 0;

   call_dump_routine (prefix);
   call_dump_routine (format, name, n);

   if (n > 0)
     {
	prefix[len] = ' ';
	len++;
	prefix[len] = 0;

	_SLdump_objects (prefix, objs, n, dir);
     }
}

/*  Pop a data item from the stack and return a pointer to it.
 *  Strings are not freed from stack so use another routine to do it.
 */
static VOID_STAR pop_pointer (SLang_Object_Type *obj, unsigned char type)
{
#ifndef _SLANG_OPTIMIZE_FOR_SPEED
   SLang_Class_Type *cl;
#endif

   SLang_Array_Type *at;

   /* Arrays are special.  Allow scalars to automatically convert to arrays.
    */
   if (type == SLANG_ARRAY_TYPE)
     {
	if (-1 == SLang_pop_array (&at, 1))
	  return NULL;
	obj->data_type = SLANG_ARRAY_TYPE;
	return obj->v.ptr_val = (VOID_STAR) at;
     }

   if (type == 0)
     {
	/* This happens when an intrinsic is declared without any information
	 * regarding parameter types.
	 */
	if (-1 == SLang_pop (obj))
	  return NULL;
	type = obj->data_type;
     }
   else if (-1 == _SLang_pop_object_of_type (type, obj, 0))
     return NULL;

#if _SLANG_OPTIMIZE_FOR_SPEED
   type = _SLclass_Class_Type [type];
#else
   type = _SLclass_get_class (type)->cl_class_type;
#endif

   if (type == SLANG_CLASS_TYPE_SCALAR)
     return (VOID_STAR) &obj->v;
   else if (type == SLANG_CLASS_TYPE_MMT)
     return SLang_object_from_mmt (obj->v.ref);
   else
     return obj->v.ptr_val;
}

/* This is ugly.  Does anyone have a advice for a cleaner way of doing
 * this??
 */
typedef void (*VF0_Type)(void);
typedef void (*VF1_Type)(VOID_STAR);
typedef void (*VF2_Type)(VOID_STAR, VOID_STAR);
typedef void (*VF3_Type)(VOID_STAR, VOID_STAR, VOID_STAR);
typedef void (*VF4_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
typedef void (*VF5_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
typedef void (*VF6_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
typedef void (*VF7_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
typedef long (*LF0_Type)(void);
typedef long (*LF1_Type)(VOID_STAR);
typedef long (*LF2_Type)(VOID_STAR, VOID_STAR);
typedef long (*LF3_Type)(VOID_STAR, VOID_STAR, VOID_STAR);
typedef long (*LF4_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
typedef long (*LF5_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
typedef long (*LF6_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
typedef long (*LF7_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
#if SLANG_HAS_FLOAT
typedef double (*FF0_Type)(void);
typedef double (*FF1_Type)(VOID_STAR);
typedef double (*FF2_Type)(VOID_STAR, VOID_STAR);
typedef double (*FF3_Type)(VOID_STAR, VOID_STAR, VOID_STAR);
typedef double (*FF4_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
typedef double (*FF5_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
typedef double (*FF6_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
typedef double (*FF7_Type)(VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR, VOID_STAR);
#endif

static int execute_intrinsic_fun (SLang_Intrin_Fun_Type *objf)
{
#if SLANG_HAS_FLOAT
   double xf;
#endif
   VOID_STAR p[SLANG_MAX_INTRIN_ARGS];
   SLang_Object_Type objs[SLANG_MAX_INTRIN_ARGS];
   long ret;
   unsigned char type;
   unsigned int argc;
   unsigned int i;
   FVOID_STAR fptr;
   unsigned char *arg_types;
   int stk_depth;

   fptr = objf->i_fun;
   argc = objf->num_args;
   type = objf->return_type;
   arg_types = objf->arg_types;

   if (argc > SLANG_MAX_INTRIN_ARGS)
     {
	SLang_verror(SL_APPLICATION_ERROR,
		     "Intrinsic function %s requires too many parameters", objf->name);
	return -1;
     }

   if (-1 == _SL_increment_frame_pointer ())
     return -1;

   stk_depth = -1;
   if (Trace_Mode && (_SLang_Trace > 0))
     {
	int nargs;

	stk_depth = _SLstack_depth ();

	nargs = SLang_Num_Function_Args;
	if (nargs == 0)
	  nargs = (int)argc;

	stk_depth -= nargs;

	if (stk_depth >= 0)
	  trace_dump (">>%s (%d args)\n",
		      objf->name,
		      _SLStack_Pointer - nargs,
		      nargs,
		      1);
     }

   i = argc;
   while (i != 0)
     {
	i--;
	if (NULL == (p[i] = pop_pointer (objs + i, arg_types[i])))
	  {
	     i++;
	     goto free_and_return;
	  }
     }

   ret = 0;
#if SLANG_HAS_FLOAT
   xf = 0.0;
#endif

   switch (argc)
     {
      case 0:
	if (type == SLANG_VOID_TYPE) ((VF0_Type) fptr) ();
#if SLANG_HAS_FLOAT
	else if (type == SLANG_DOUBLE_TYPE) xf = ((FF0_Type) fptr)();
#endif
	else ret = ((LF0_Type) fptr)();
	break;

      case 1:
	if (type == SLANG_VOID_TYPE) ((VF1_Type) fptr)(p[0]);
#if SLANG_HAS_FLOAT
	else if (type == SLANG_DOUBLE_TYPE) xf =  ((FF1_Type) fptr)(p[0]);
#endif
	else ret =  ((LF1_Type) fptr)(p[0]);
	break;

      case 2:
	if (type == SLANG_VOID_TYPE)  ((VF2_Type) fptr)(p[0], p[1]);
#if SLANG_HAS_FLOAT
	else if (type == SLANG_DOUBLE_TYPE) xf = ((FF2_Type) fptr)(p[0], p[1]);
#endif
	else ret = ((LF2_Type) fptr)(p[0], p[1]);
	break;

      case 3:
	if (type == SLANG_VOID_TYPE) ((VF3_Type) fptr)(p[0], p[1], p[2]);
#if SLANG_HAS_FLOAT
	else if (type == SLANG_DOUBLE_TYPE) xf = ((FF3_Type) fptr)(p[0], p[1], p[2]);
#endif
	else ret = ((LF3_Type) fptr)(p[0], p[1], p[2]);
	break;

      case 4:
	if (type == SLANG_VOID_TYPE) ((VF4_Type) fptr)(p[0], p[1], p[2], p[3]);
#if SLANG_HAS_FLOAT
	else if (type == SLANG_DOUBLE_TYPE) xf = ((FF4_Type) fptr)(p[0], p[1], p[2], p[3]);
#endif
	else ret = ((LF4_Type) fptr)(p[0], p[1], p[2], p[3]);
	break;

      case 5:
	if (type == SLANG_VOID_TYPE) ((VF5_Type) fptr)(p[0], p[1], p[2], p[3], p[4]);
#if SLANG_HAS_FLOAT
	else if (type == SLANG_DOUBLE_TYPE) xf = ((FF5_Type) fptr)(p[0], p[1], p[2], p[3], p[4]);
#endif
	else ret = ((LF5_Type) fptr)(p[0], p[1], p[2], p[3], p[4]);
	break;

      case 6:
	if (type == SLANG_VOID_TYPE) ((VF6_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5]);
#if SLANG_HAS_FLOAT
	else if (type == SLANG_DOUBLE_TYPE) xf = ((FF6_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5]);
#endif
	else ret = ((LF6_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5]);
	break;

      case 7:
	if (type == SLANG_VOID_TYPE) ((VF7_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
#if SLANG_HAS_FLOAT
	else if (type == SLANG_DOUBLE_TYPE) xf = ((FF7_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
#endif
	else ret = ((LF7_Type) fptr)(p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
	break;
     }

   switch (type)
     {
      case SLANG_VOID_TYPE:
	break;
	
#if SLANG_HAS_FLOAT
      case SLANG_DOUBLE_TYPE:
	(void) SLang_push_double (xf);
	break;
#endif
      case SLANG_UINT_TYPE:
      case SLANG_INT_TYPE: (void) SLclass_push_int_obj (type, (int) ret);
	break;
	
      case SLANG_CHAR_TYPE:
      case SLANG_UCHAR_TYPE: (void) SLclass_push_char_obj (type, (char) ret);
	break;

      case SLANG_SHORT_TYPE:
      case SLANG_USHORT_TYPE: (void) SLclass_push_short_obj (type, (short) ret);
	break;

      case SLANG_LONG_TYPE:
      case SLANG_ULONG_TYPE: (void) SLclass_push_long_obj (type, ret);
	break;
	
      case SLANG_STRING_TYPE:
	if (NULL == (char *)ret)
	  {
	     if (SLang_Error == 0) SLang_Error = SL_INTRINSIC_ERROR;
	  }
	else (void) SLang_push_string ((char *)ret);
	break;
	
      default:
	SLang_verror (SL_NOT_IMPLEMENTED,
		      "Support for intrinsic functions returning %s is not provided",
		      SLclass_get_datatype_name (type));
     }

   if (stk_depth >= 0)
     {
	stk_depth = _SLstack_depth () - stk_depth;

	trace_dump ("<<%s (returning %d values)\n",
		      objf->name,
		      _SLStack_Pointer - stk_depth,
		      stk_depth,
		      1);
     }

   free_and_return:
   while (i < argc)
     {
	SLang_free_object (objs + i);
	i++;
     }

   return _SL_decrement_frame_pointer ();
}

static int inner_interp(register SLBlock_Type *);

/* Switch_Obj_Ptr points to the NEXT available free switch object */
static SLang_Object_Type Switch_Objects[SLANG_MAX_NESTED_SWITCH];
static SLang_Object_Type *Switch_Obj_Ptr = Switch_Objects;
static SLang_Object_Type *Switch_Obj_Max = Switch_Objects + SLANG_MAX_NESTED_SWITCH;

static void
lang_do_loops (unsigned char stype, SLBlock_Type *block, unsigned int num_blocks)
{
   int i, ctrl;
   int first, last;
   SLBlock_Type *blks[4];
   char *loop_name;
   SLang_Foreach_Context_Type *foreach_context;
   SLang_Class_Type *cl;
   int type;
   unsigned int j;

   j = 0;
   for (i = 0; i < (int) num_blocks; i++)
     {
	if (block[i].bc_main_type != _SLANG_BC_BLOCK)
	  {
	     if (block[i].bc_main_type == _SLANG_BC_LINE_NUM)
	       continue;

	     SLang_verror (SL_SYNTAX_ERROR, "Bytecode is not a looping block");
	     return;
	  }
	blks[j] = block[i].b.blk;
	j++;
     }

   num_blocks = j;
   block = blks[0];

   switch (stype)
     {
      case _SLANG_BCST_FOREACH:
	loop_name = "foreach";
	if (num_blocks != 1)
	  goto wrong_num_blocks_error;

	/* We should find Next_Function_Num_Args + 1 items on the stack.
	 * The first Next_Function_Num_Args items represent the arguments to
	 * to USING.  The last item (deepest in stack) is the object to loop
	 * over.  So, roll the stack up and grab it.
	 */
	if ((-1 == SLroll_stack (-(Next_Function_Num_Args + 1)))
	    || (-1 == (type = SLang_peek_at_stack ())))
	  goto return_error;

	cl = _SLclass_get_class ((unsigned char) type);
	if ((cl->cl_foreach == NULL)
	    || (cl->cl_foreach_open == NULL)
	    || (cl->cl_foreach_close == NULL))
	  {
	     SLang_verror (SL_NOT_IMPLEMENTED, "%s does not permit foreach", cl->cl_name);
	     SLdo_pop_n (Next_Function_Num_Args + 1);
	     goto return_error;
	  }

	if (NULL == (foreach_context = (*cl->cl_foreach_open) ((unsigned char)type, Next_Function_Num_Args)))
	  goto return_error;

	while (1)
	  {
	     int status;

	     if (SLang_Error)
	       {
		  (*cl->cl_foreach_close) ((unsigned char) type, foreach_context);
		  goto return_error;
	       }

	     status = (*cl->cl_foreach) ((unsigned char) type, foreach_context);
	     if (status <= 0)
	       {
		  if (status == 0)
		    break;

		  (*cl->cl_foreach_close) ((unsigned char) type, foreach_context);
		  goto return_error;
	       }

	     inner_interp (block);
	     if (Lang_Break) break;
	     Lang_Break_Condition = /* Lang_Continue = */ 0;
	  }
	(*cl->cl_foreach_close) ((unsigned char) type, foreach_context);
	break;

      case _SLANG_BCST_WHILE:
	loop_name = "while";

	if (num_blocks != 2)
	  goto wrong_num_blocks_error;

	type = blks[1]->bc_main_type;
	while (1)
	  {
	     if (SLang_Error)
	       goto return_error;

	     inner_interp (block);
	     if (Lang_Break) break;

	     if (-1 == pop_ctrl_integer (&ctrl))
	       goto return_error;

	     if (ctrl == 0) break;

	     if (type)
	       {
		  inner_interp (blks[1]);
		  if (Lang_Break) break;
		  Lang_Break_Condition = /* Lang_Continue = */ 0;
	       }
	  }
	break;

      case _SLANG_BCST_DOWHILE:
	loop_name = "do...while";

	if (num_blocks != 2)
	  goto wrong_num_blocks_error;

	while (1)
	  {
	     if (SLang_Error)
	       goto return_error;

	     Lang_Break_Condition = /* Lang_Continue = */ 0;
	     inner_interp (block);
	     if (Lang_Break) break;
	     Lang_Break_Condition = /* Lang_Continue = */ 0;
	     inner_interp (blks[1]);
	     if (-1 == pop_ctrl_integer (&ctrl))
	       goto return_error;

	     if (ctrl == 0) break;
	  }
	break;

      case _SLANG_BCST_CFOR:
	loop_name = "for";

	/* we need 4 blocks: first 3 control, the last is code */
	if (num_blocks != 4) goto wrong_num_blocks_error;

	inner_interp (block);
	while (1)
	  {
	     if (SLang_Error)
	       goto return_error;

	     inner_interp(blks[1]);       /* test */
	     if (-1 == pop_ctrl_integer (&ctrl))
	       goto return_error;

	     if (ctrl == 0) break;
	     inner_interp(blks[3]);       /* code */
	     if (Lang_Break) break;
	     inner_interp(blks[2]);       /* bump */
	     Lang_Break_Condition = /* Lang_Continue = */ 0;
	  }
	break;

      case _SLANG_BCST_FOR:
	loop_name = "_for";

	if (num_blocks != 1)
	  goto wrong_num_blocks_error;

	/* 3 elements: first, last, step */
	if ((-1 == SLang_pop_integer (&ctrl))
	    || (-1 == SLang_pop_integer (&last))
	    || (-1 == SLang_pop_integer (&first)))
	  goto return_error;

	i = first;
	while (1)
	  {
	     /* It is ugly to have this test here but I do not know of a
	      * simple way to do this without using two while loops.
	      */
	     if (ctrl >= 0)
	       {
		  if (i > last) break;
	       }
	     else if (i < last) break;

	     if (SLang_Error) goto return_error;

	     SLclass_push_int_obj (SLANG_INT_TYPE, i);
	     inner_interp (block);
	     if (Lang_Break) break;
	     Lang_Break_Condition = /* Lang_Continue = */ 0;

	     i += ctrl;
	  }
	break;

      case _SLANG_BCST_LOOP:
	loop_name = "loop";
	if (num_blocks != 1)
	  goto wrong_num_blocks_error;

	if (-1 == SLang_pop_integer (&ctrl))
	  goto return_error;
	while (ctrl > 0)
	  {
	     ctrl--;

	     if (SLang_Error)
	       goto return_error;

	     inner_interp (block);
	     if (Lang_Break) break;
	     Lang_Break_Condition = /* Lang_Continue = */ 0;
	  }
	break;

      case _SLANG_BCST_FOREVER:
	loop_name = "forever";

	if (num_blocks != 1)
	  goto wrong_num_blocks_error;

	while (1)
	  {
	     if (SLang_Error)
	       goto return_error;

	     inner_interp (block);
	     if (Lang_Break) break;
	     Lang_Break_Condition = /* Lang_Continue = */ 0;
	  }
	break;

      default:  SLang_verror(SL_INTERNAL_ERROR, "Unknown loop type");
	return;
     }
   Lang_Break = /* Lang_Continue = */ 0;
   Lang_Break_Condition = Lang_Return;
   return;

   wrong_num_blocks_error:
   SLang_verror (SL_SYNTAX_ERROR, "Wrong number of blocks for '%s' construct", loop_name);

   /* drop */
   return_error:
   do_traceback (loop_name, 0, NULL);
}

static void lang_do_and_orelse (unsigned char stype, SLBlock_Type *addr, SLBlock_Type *addr_max)
{
   int test = 0;
   int is_or;

   is_or = (stype == _SLANG_BCST_ORELSE);

   while (addr <= addr_max)
     {
	if (addr->bc_main_type == _SLANG_BC_LINE_NUM)
	  {
	     addr++;
	     continue;
	  }

	inner_interp (addr->b.blk);
	if (SLang_Error
	    || Lang_Break_Condition
	    || (-1 == pop_ctrl_integer (&test)))
	  return;

	if (is_or == (test != 0))
	  break;

	/* if (((stype == _SLANG_BCST_ANDELSE) && (test == 0))
	 *   || ((stype == _SLANG_BCST_ORELSE) && test))
	 * break;
	 */

	addr++;
     }
   SLclass_push_int_obj (SLANG_INT_TYPE, test);
}

static void do_else_if (SLBlock_Type *zero_block, SLBlock_Type *non_zero_block)
{
   int test;

   if (-1 == pop_ctrl_integer (&test))
     return;

   if (test == 0)
     non_zero_block = zero_block;

   if (non_zero_block != NULL)
     inner_interp (non_zero_block->b.blk);
}

int _SLang_trace_fun (char *f)
{
   if (NULL == (f = SLang_create_slstring (f)))
     return -1;

   SLang_free_slstring (Trace_Function);
   Trace_Function = f;
   _SLang_Trace = 1;
   return 0;
}

int _SLdump_objects (char *prefix, SLang_Object_Type *x, unsigned int n, int dir)
{
   char *s;
   SLang_Class_Type *cl;

   while (n)
     {
	cl = _SLclass_get_class (x->data_type);

	if (NULL == (s = _SLstringize_object (x)))
	  s = "??";

	call_dump_routine ("%s[%s]:%s\n", prefix, cl->cl_name, s);

	SLang_free_slstring (s);

	x += dir;
	n--;
     }
   return 0;
}

static SLBlock_Type *Exit_Block_Ptr;
static SLBlock_Type *Global_User_Block[5];
static SLBlock_Type **User_Block_Ptr = Global_User_Block;
char *_SLang_Current_Function_Name = NULL;

static int execute_slang_fun (_SLang_Function_Type *fun)
{
   register unsigned int i;
   register SLang_Object_Type *frame, *lvf;
   register unsigned int n_locals;
   _SLBlock_Header_Type *header;
   /* SLBlock_Type *val; */
   SLBlock_Type *exit_block_save;
   SLBlock_Type **user_block_save;
   SLBlock_Type *user_blocks[5];
   char *save_fname;

   exit_block_save = Exit_Block_Ptr;
   user_block_save = User_Block_Ptr;
   User_Block_Ptr = user_blocks;
   *(user_blocks) = NULL;
   *(user_blocks + 1) = NULL;
   *(user_blocks + 2) = NULL;
   *(user_blocks + 3) = NULL;
   *(user_blocks + 4) = NULL;

   Exit_Block_Ptr = NULL;

   save_fname = _SLang_Current_Function_Name;
   _SLang_Current_Function_Name = fun->name;

   _SL_increment_frame_pointer ();

   /* need loaded?  */
   if (fun->nlocals == AUTOLOAD_NUM_LOCALS)
     {
	header = NULL;
	if (-1 == SLang_load_file(fun->v.autoload_filename))
	  goto the_return;

	if (fun->nlocals == AUTOLOAD_NUM_LOCALS)
	  {
	     SLang_verror (SL_UNDEFINED_NAME, "%s: Function did not autoload",
			   _SLang_Current_Function_Name);
             goto the_return;
	  }
     }

   n_locals = fun->nlocals;

   /* let the error propagate through since it will do no harm
    and allow us to restore stack. */

   /* set new stack frame */
   lvf = frame = Local_Variable_Frame;
   i = n_locals;
   if ((lvf + i) > Local_Variable_Stack + SLANG_MAX_LOCAL_STACK)
     {
	SLang_verror(SL_STACK_OVERFLOW, "%s: Local Variable Stack Overflow",
		     _SLang_Current_Function_Name);
	goto the_return;
     }

   /* Make sure we do not allow this header to get destroyed by something
    * like:  define crash () { eval ("define crash ();") }
    */
   header = fun->v.header;
   header->num_refs++;

   while (i--)
     {
	lvf++;
	lvf->data_type = SLANG_UNDEFINED_TYPE;
     }
   Local_Variable_Frame = lvf;

   /* read values of function arguments */
   i = fun->nargs;
   while (i > 0)
     {
	i--;
	(void) SLang_pop (Local_Variable_Frame - i);
     }

   if (SLang_Enter_Function != NULL) (*SLang_Enter_Function)(_SLang_Current_Function_Name);

   if (_SLang_Trace)
     {
	int stack_depth;

	stack_depth = _SLstack_depth ();

	if ((Trace_Function != NULL)
	    && (0 == strcmp (Trace_Function, _SLang_Current_Function_Name))
	    && (Trace_Mode == 0))
	  Trace_Mode = 1;

	if (Trace_Mode)
	  {
	     /* The local variable frame grows backwards */
	     trace_dump (">>%s (%d args)\n",
			 _SLang_Current_Function_Name,
			 Local_Variable_Frame,
			 (int) fun->nargs,
			 -1);
	     Trace_Mode++;
	  }

	inner_interp (header->body);
	Lang_Break_Condition = Lang_Return = Lang_Break = 0;
	if (Exit_Block_Ptr != NULL) inner_interp(Exit_Block_Ptr);

	if (Trace_Mode)
	  {
	     Trace_Mode--;
	     stack_depth = _SLstack_depth () - stack_depth;

	     trace_dump ("<<%s (returning %d values)\n",
			 _SLang_Current_Function_Name,
			 _SLStack_Pointer - stack_depth,
			 stack_depth,
			 1);

	     if (Trace_Mode == 1)
	       Trace_Mode = 0;
	  }
     }
   else
     {
	inner_interp (header->body);
	Lang_Break_Condition = Lang_Return = Lang_Break = 0;
	if (Exit_Block_Ptr != NULL) inner_interp(Exit_Block_Ptr);
     }

   if (SLang_Exit_Function != NULL) (*SLang_Exit_Function)(_SLang_Current_Function_Name);

   if (SLang_Error)
     do_traceback(fun->name, n_locals,
#if _SLANG_HAS_DEBUG_CODE
		  fun->file
#else
		  NULL
#endif
		  );

   /* free local variables.... */
   lvf = Local_Variable_Frame;
   while (lvf > frame)
     {
#if _SLANG_OPTIMIZE_FOR_SPEED
	if (SLANG_CLASS_TYPE_SCALAR != _SLclass_Class_Type [lvf->data_type])
#endif
	  SLang_free_object (lvf);
	lvf--;
     }
   Local_Variable_Frame = lvf;

   if (header->num_refs == 1)
     free_function_header (header);
   else
     header->num_refs--;

   the_return:

   Lang_Break_Condition = Lang_Return = Lang_Break = 0;
   Exit_Block_Ptr = exit_block_save;
   User_Block_Ptr = user_block_save;
   _SLang_Current_Function_Name = save_fname;
   _SL_decrement_frame_pointer ();

   if (SLang_Error)
     return -1;

   return 0;
}

static void do_traceback (char *name, unsigned int locals, char *file)
{
   char *s;
   unsigned int i;
   SLang_Object_Type *objp;
   unsigned short stype;

   /* FIXME: Priority=low
    * I need to make this configurable!!! That is, let the
    * application decide whether or not a usage error should result in a
    * traceback.
    */
   if (SLang_Error == SL_USAGE_ERROR)
     return;

   if (SLang_Traceback == 0)
     return;

   call_dump_routine ("S-Lang Traceback: %s\n", name);
   if (SLang_Traceback < 0)
     return;

   if (file != NULL)
     call_dump_routine ("File: %s\n", file);

   if (locals == 0)
     return;

   call_dump_routine ("  Local Variables:\n");

   for (i = 0; i < locals; i++)
     {
	SLang_Class_Type *cl;
	char *class_name;

	objp = Local_Variable_Frame - i;
	stype = objp->data_type;

	s = _SLstringize_object (objp);
	cl = _SLclass_get_class (stype);
	class_name = cl->cl_name;

	call_dump_routine ("\t$%d: Type: %s,\tValue:\t", i, class_name);

	if (s == NULL) call_dump_routine("??\n");
	else
	  {
	     char *q = "";
#ifndef HAVE_VSNPRINTF
	     char buf[256];
	     if (strlen (s) >= sizeof (buf))
	       {
		  strncpy (buf, s, sizeof(buf));
		  s = buf;
		  s[sizeof(buf) - 1] = 0;
	       }
#endif
	     if (SLANG_STRING_TYPE == stype) q = "\"";
	     call_dump_routine ("%s%s%s\n", q, s, q);
	  }
     }
}

static void do_app_unary (SLang_App_Unary_Type *nt)
{
   if (-1 == do_unary (nt->unary_op, nt->name_type))
     do_traceback (nt->name, 0, NULL);
}

static int inner_interp_nametype (SLang_Name_Type *nt)
{
   SLBlock_Type bc_blks[2];

   bc_blks[0].b.nt_blk = nt;
   bc_blks[0].bc_main_type = nt->name_type;
   bc_blks[1].bc_main_type = 0;
   return inner_interp(bc_blks);
}

int _SLang_dereference_ref (SLang_Ref_Type *ref)
{
   if (ref == NULL)
     {
	SLang_Error = SL_INTERNAL_ERROR;
	return -1;
     }

   if (ref->is_global == 0)
     {
	SLang_Object_Type *obj = ref->v.local_obj;
	if (obj > Local_Variable_Frame)
	  {
	     SLang_verror (SL_UNDEFINED_NAME, "Local variable deref is out of scope");
	     return -1;
	  }
	return _SLpush_slang_obj (ref->v.local_obj);
     }

   (void) inner_interp_nametype (ref->v.nt);
   return 0;
}

int _SLang_is_ref_initialized (SLang_Ref_Type *ref)
{
   unsigned char type;

   if (ref == NULL)
     {
	SLang_Error = SL_INTERNAL_ERROR;
	return -1;
     }

   if (ref->is_global == 0)
     {
	SLang_Object_Type *obj = ref->v.local_obj;
	if (obj > Local_Variable_Frame)
	  {
	     SLang_verror (SL_UNDEFINED_NAME, "Local variable deref is out of scope");
	     return -1;
	  }
	type = ref->v.local_obj->data_type;
     }
   else
     {
	SLang_Name_Type *nt = ref->v.nt;
	if ((nt->name_type != SLANG_GVARIABLE)
	    && (nt->name_type != SLANG_PVARIABLE))
	  return 1;
	type = ((SLang_Global_Var_Type *)nt)->obj.data_type;
     }
   return type != SLANG_UNDEFINED_TYPE;
}

int _SLang_uninitialize_ref (SLang_Ref_Type *ref)
{
   SLang_Object_Type *obj;

   if (ref == NULL)
     {
	SLang_Error = SL_INTERNAL_ERROR;
	return -1;
     }

   if (ref->is_global == 0)
     {
	obj = ref->v.local_obj;
	if (obj > Local_Variable_Frame)
	  {
	     SLang_verror (SL_UNDEFINED_NAME, "Local variable deref is out of scope");
	     return -1;
	  }
	obj = ref->v.local_obj;
     }
   else
     {
	SLang_Name_Type *nt = ref->v.nt;
	if ((nt->name_type != SLANG_GVARIABLE)
	    && (nt->name_type != SLANG_PVARIABLE))
	  return -1;
	obj = &((SLang_Global_Var_Type *)nt)->obj;
     }
   SLang_free_object (obj);
   obj->data_type = SLANG_UNDEFINED_TYPE;
   obj->v.ptr_val = NULL;
   return 0;
}

void (*SLang_Interrupt)(void);
static int Last_Error;
void (*SLang_User_Clear_Error)(void);
void _SLang_clear_error (void)
{
   if (Last_Error <= 0)
     {
	Last_Error = 0;
	return;
     }
   Last_Error--;
   if (SLang_User_Clear_Error != NULL) (*SLang_User_Clear_Error)();
}

int _SLpush_slang_obj (SLang_Object_Type *obj)
{
   unsigned char subtype;
   SLang_Class_Type *cl;

   if (obj == NULL) return SLang_push_null ();

   subtype = obj->data_type;

#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type[subtype])
     return SLang_push (obj);
#endif

   cl = _SLclass_get_class (subtype);
   return (*cl->cl_push) (subtype, (VOID_STAR) &obj->v);
}

_INLINE_
static int push_local_variable (int i)
{
   SLang_Class_Type *cl;
   SLang_Object_Type *obj;
   unsigned char subtype;

   obj = Local_Variable_Frame - i;
   subtype = obj->data_type;

#if _SLANG_OPTIMIZE_FOR_SPEED
   if (SLANG_CLASS_TYPE_SCALAR == _SLclass_Class_Type[subtype])
     return SLang_push (obj);
   if (subtype == SLANG_STRING_TYPE)
     return _SLang_dup_and_push_slstring (obj->v.s_val);
#endif

   cl = _SLclass_get_class (subtype);
   return (*cl->cl_push) (subtype, (VOID_STAR) &obj->v);
}

static int push_intrinsic_variable (SLang_Intrin_Var_Type *ivar)
{
   SLang_Class_Type *cl;
   unsigned char stype;

   stype = ivar->type;
   cl = _SLclass_get_class (stype);

   if (-1 == (*cl->cl_push_intrinsic) (stype, ivar->addr))
     {
	do_name_type_error ((SLang_Name_Type *) ivar);
	return -1;
     }
   return 0;
}

static int dereference_object (void)
{
   SLang_Object_Type obj;
   SLang_Class_Type *cl;
   unsigned char type;
   int ret;

   if (-1 == SLang_pop (&obj))
     return -1;

   type = obj.data_type;

   cl = _SLclass_get_class (type);
   ret = (*cl->cl_dereference)(type, (VOID_STAR) &obj.v);

   SLang_free_object (&obj);
   return ret;
}

static int case_function (void)
{
   unsigned char type;
   SLang_Object_Type obj;
   SLang_Object_Type *swobjptr;

   swobjptr = Switch_Obj_Ptr - 1;

   if ((swobjptr < Switch_Objects)
       || (0 == (type = swobjptr->data_type)))
     {
	SLang_verror (SL_SYNTAX_ERROR, "Misplaced 'case' keyword");
	return -1;
     }

   if (-1 == SLang_pop (&obj))
     return -1;

   if (obj.data_type != type)
     {
	SLang_Class_Type *a_cl, *b_cl;

	a_cl = _SLclass_get_class (obj.data_type);
	b_cl = _SLclass_get_class (type);

	if (NULL == _SLclass_get_binary_fun (SLANG_EQ, a_cl, b_cl, &a_cl, 0))
	  {
	     (void) SLclass_push_int_obj (SLANG_INT_TYPE, 0);
	     SLang_free_object (&obj);
	     return 0;
	  }
     }

   (void) do_binary_ab (SLANG_EQ, swobjptr, &obj);
   SLang_free_object (&obj);
   return 0;
}

static void tmp_variable_function (SLBlock_Type *addr)
{
   SLang_Object_Type *obj;

   switch (addr->bc_sub_type)
     {
      case SLANG_GVARIABLE:
      case SLANG_PVARIABLE:
	obj = &addr->b.nt_gvar_blk->obj;
	break;

      case SLANG_LVARIABLE:
	obj = Local_Variable_Frame - addr->b.i_blk;
	break;

      default:
	SLang_Error = SL_INTERNAL_ERROR;
	return;
     }

   /* There is no need to go through higher level routines since we are
    * not creating or destroying extra copies.
    */
   if (-1 == SLang_push (obj))
     return;

   obj->data_type = SLANG_UNDEFINED_TYPE;
   obj->v.ptr_val = NULL;
}


static int
do_inner_interp_error (SLBlock_Type *err_block,
		       SLBlock_Type *addr_start,
		       SLBlock_Type *addr)
{
   int save_err, slerr;

   /* Someday I can use the these variable to provide extra information
    * about what went wrong.
    */
   (void) addr_start;
   (void) addr;

   if (err_block == NULL)
     goto return_error;

   if (SLang_Error < 0)		       /* errors less than 0 are severe */
     goto return_error;

   save_err = Last_Error++;
   slerr = SLang_Error;
   SLang_Error = 0;
   inner_interp (err_block->b.blk);

   if (Last_Error <= save_err)
     {
	/* Caught error and cleared it */
	Last_Error = save_err;
	if ((Lang_Break_Condition == 0)
	    /* An error may have cleared the error and then caused the
	     * function to return.  We will allow that but let's not allow
	     * 'break' nor 'continue' statements until later.
	     */
	    || Lang_Return)
	  return 0;

	/* drop--- either a break or continue was called */
     }

   Last_Error = save_err;
   SLang_Error = slerr;

   return_error:
#if _SLANG_HAS_DEBUG_CODE
   while (addr >= addr_start)
     {
	if (addr->bc_main_type == _SLANG_BC_LINE_NUM)
	  {
	     char buf[256];
	     sprintf (buf, "(Error occurred on line %lu)", addr->b.l_blk);
	     do_traceback (buf, 0, NULL);
	     break;
	  }
	/* Special hack for 16 bit systems to prevent pointer wrapping. */
#if defined(__16_BIT_SYSTEM__)
	if (addr == addr_start)
	  break;
#endif
	addr--;
     }
#endif
   return -1;
}


#define GATHER_STATISTICS 0
#if GATHER_STATISTICS
static unsigned int Bytecodes[0xFFFF];

static void print_stats (void)
{
   unsigned int i;
   unsigned long total;
   FILE *fp = fopen ("stats.txt", "w");
   if (fp == NULL)
     return;
   
   total = 0;
   for (i = 0; i < 0xFFFF; i++)
     total += Bytecodes[i];
   
   if (total == 0)
     total = 1;

   for (i = 0; i < 0xFFFF; i++)
     {
	if (Bytecodes[i])
	  fprintf (fp, "0x%04X %9u %e\n", i, Bytecodes[i], Bytecodes[i]/(double) total);
     }
   fclose (fp);
}

static void add_to_statistics (SLBlock_Type *b)
{
   unsigned short x, y;
   
   x = b->bc_main_type;
   if (x == 0)
     {
	Bytecodes[0] += 1;
	return;
     }
   b++;
   y = b->bc_main_type;

   Bytecodes[(x << 8) | y] += 1;
}

#endif

/* inner interpreter */
/* The return value from this function is only meaningful when it is used
 * to process blocks for the switch statement.  If it returns 0, the calling
 * routine should pass the next block to it.  Otherwise it will
 * return non-zero, with or without error.
 */
static int inner_interp (SLBlock_Type *addr_start)
{
   SLBlock_Type *block, *err_block, *addr;
#if GATHER_STATISTICS
   static int inited = 0;

   if (inited == 0)
     {
	(void) SLang_add_cleanup_function (print_stats);
	inited = 1;
     }
#endif

   /* for systems that have no real interrupt facility (e.g. go32 on dos) */
   if (SLang_Interrupt != NULL) (*SLang_Interrupt)();

   block = err_block = NULL;
   addr = addr_start;

#if GATHER_STATISTICS
   add_to_statistics (addr);
#endif
   while (1)
     {
	switch (addr->bc_main_type)
	  {
	   case 0:
	     return 1;
	   case _SLANG_BC_LVARIABLE:
	     push_local_variable (addr->b.i_blk);
	     break;
	   case _SLANG_BC_GVARIABLE:
	     if (-1 == _SLpush_slang_obj (&addr->b.nt_gvar_blk->obj))
	       do_name_type_error (addr->b.nt_blk);
	     break;

	   case _SLANG_BC_IVARIABLE:
	   case _SLANG_BC_RVARIABLE:
	     push_intrinsic_variable (addr->b.nt_ivar_blk);
	     break;

	   case _SLANG_BC_INTRINSIC:
	     execute_intrinsic_fun (addr->b.nt_ifun_blk);
	     if (SLang_Error)
	       do_traceback(addr->b.nt_ifun_blk->name, 0, NULL);
	     break;

	   case _SLANG_BC_FUNCTION:
	     execute_slang_fun (addr->b.nt_fun_blk);
	     if (Lang_Break_Condition) goto handle_break_condition;
	     break;

	   case _SLANG_BC_MATH_UNARY:
	   case _SLANG_BC_APP_UNARY:
	     /* Make sure we treat these like function calls since the
	      * parser took sin(x) to be a function call.
	      */
	     if (0 == _SL_increment_frame_pointer ())
	       {
		  do_app_unary (addr->b.nt_unary_blk);
		  (void) _SL_decrement_frame_pointer ();
	       }
	     break;

	   case _SLANG_BC_ICONST:
	     SLclass_push_int_obj (SLANG_INT_TYPE, addr->b.iconst_blk->i);
	     break;

#if SLANG_HAS_FLOAT
	   case _SLANG_BC_DCONST:
	     SLang_push_double (addr->b.dconst_blk->d);
	     break;
#endif

	   case _SLANG_BC_PVARIABLE:
	     if (-1 == _SLpush_slang_obj (&addr->b.nt_gvar_blk->obj))
	       do_name_type_error (addr->b.nt_blk);
	     break;

	   case _SLANG_BC_PFUNCTION:
	     execute_slang_fun (addr->b.nt_fun_blk);
	     if (Lang_Break_Condition) goto handle_break_condition;
	     break;

	   case _SLANG_BC_BINARY:
	     do_binary (addr->b.i_blk);
	     break;
	     
	   case _SLANG_BC_LITERAL:
#if !_SLANG_OPTIMIZE_FOR_SPEED
	   case _SLANG_BC_LITERAL_INT:
	   case _SLANG_BC_LITERAL_STR:
#endif
	       {
		  SLang_Class_Type *cl = _SLclass_get_class (addr->bc_sub_type);
		  (*cl->cl_push_literal) (addr->bc_sub_type, (VOID_STAR) &addr->b.ptr_blk);
	       }
	     break;
#if _SLANG_OPTIMIZE_FOR_SPEED
	   case _SLANG_BC_LITERAL_INT:
	     SLclass_push_int_obj (addr->bc_sub_type, (int) addr->b.l_blk);
	     break;

	   case _SLANG_BC_LITERAL_STR:
	     _SLang_dup_and_push_slstring (addr->b.s_blk);
	     break;
#endif
	   case _SLANG_BC_BLOCK:
	     switch (addr->bc_sub_type)
	       {
		case _SLANG_BCST_ERROR_BLOCK:
		  err_block = addr;
		  break;

		case _SLANG_BCST_EXIT_BLOCK:
		  Exit_Block_Ptr = addr->b.blk;
		  break;

		case _SLANG_BCST_USER_BLOCK0:
		case _SLANG_BCST_USER_BLOCK1:
		case _SLANG_BCST_USER_BLOCK2:
		case _SLANG_BCST_USER_BLOCK3:
		case _SLANG_BCST_USER_BLOCK4:
		  User_Block_Ptr[addr->bc_sub_type - _SLANG_BCST_USER_BLOCK0] = addr->b.blk;
		  break;

		case _SLANG_BCST_LOOP:
		case _SLANG_BCST_WHILE:
		case _SLANG_BCST_FOR:
		case _SLANG_BCST_FOREVER:
		case _SLANG_BCST_CFOR:
		case _SLANG_BCST_DOWHILE:
		case _SLANG_BCST_FOREACH:
		  if (block == NULL) block = addr;
		  lang_do_loops(addr->bc_sub_type, block, 1 + (unsigned int) (addr - block));
		  block = NULL;
		  break;

		case _SLANG_BCST_IFNOT:
#if _SLANG_OPTIMIZE_FOR_SPEED
		    {
		       int i;
		       
		       if ((0 == pop_ctrl_integer (&i)) && (i == 0))
			 inner_interp (addr->b.blk);
		    }
#else
		  do_else_if (addr, NULL);
#endif
		  break;

		case _SLANG_BCST_IF:
#if _SLANG_OPTIMIZE_FOR_SPEED
		    {
		       int i;
		       
		       if ((0 == pop_ctrl_integer (&i)) && i)
			 inner_interp (addr->b.blk);
		    }
#else
		  do_else_if (NULL, addr);
#endif
		  break;

		case _SLANG_BCST_NOTELSE:
		  do_else_if (block, addr);
		  block = NULL;
		  break;

		case _SLANG_BCST_ELSE:
		  do_else_if (addr, block);
		  block = NULL;
		  break;

		case _SLANG_BCST_SWITCH:
		  if (Switch_Obj_Ptr == Switch_Obj_Max)
		    {
		       SLang_doerror("switch nesting too deep");
		       break;
		    }
		  (void) SLang_pop (Switch_Obj_Ptr);
		  Switch_Obj_Ptr++;

		  if (block == NULL) block = addr;
		  while ((SLang_Error == 0)
			 && (block <= addr)
			 && (Lang_Break_Condition == 0)
			 && (0 == inner_interp (block->b.blk)))
		    block++;
		  Switch_Obj_Ptr--;
		  SLang_free_object (Switch_Obj_Ptr);
		  Switch_Obj_Ptr->data_type = 0;
		  block = NULL;
		  break;

		case _SLANG_BCST_ANDELSE:
		case _SLANG_BCST_ORELSE:
		  if (block == NULL) block = addr;
		  lang_do_and_orelse (addr->bc_sub_type, block, addr);
		  block = NULL;
		  break;

		default:
		  if (block == NULL) block =  addr;
		  break;
	       }
	     if (Lang_Break_Condition) goto handle_break_condition;
	     break;

	   case _SLANG_BC_RETURN:
	     Lang_Break_Condition = Lang_Return = Lang_Break = 1; return 1;
	   case _SLANG_BC_BREAK:
	     Lang_Break_Condition = Lang_Break = 1; return 1;
	   case _SLANG_BC_CONTINUE:
	     Lang_Break_Condition = /* Lang_Continue = */ 1; return 1;

	   case _SLANG_BC_EXCH:
	     (void) SLreverse_stack (2);
	     break;

	   case _SLANG_BC_LABEL:
	       {
		  int test;
		  if ((0 == SLang_pop_integer (&test))
		      && (test == 0))
		    return 0;
	       }
	     break;

	   case _SLANG_BC_LOBJPTR:
	     (void)_SLang_push_ref (0, (VOID_STAR)(Local_Variable_Frame - addr->b.i_blk));
	     break;

	   case _SLANG_BC_GOBJPTR:
	     (void)_SLang_push_ref (1, (VOID_STAR)addr->b.nt_blk);
	     break;

	   case _SLANG_BC_X_ERROR:
	     if (err_block != NULL)
	       {
		  inner_interp(err_block->b.blk);
		  if (SLang_Error) err_block = NULL;
	       }
	     else SLang_verror(SL_SYNTAX_ERROR, "No ERROR_BLOCK");
	     if (Lang_Break_Condition) goto handle_break_condition;
	     break;

	   case _SLANG_BC_X_USER0:
	   case _SLANG_BC_X_USER1:
	   case _SLANG_BC_X_USER2:
	   case _SLANG_BC_X_USER3:
	   case _SLANG_BC_X_USER4:
	     if (User_Block_Ptr[addr->bc_main_type - _SLANG_BC_X_USER0] != NULL)
	       {
		  inner_interp(User_Block_Ptr[addr->bc_main_type - _SLANG_BC_X_USER0]);
	       }
	     else SLang_verror(SL_SYNTAX_ERROR, "No block for X_USERBLOCK");
	     if (Lang_Break_Condition) goto handle_break_condition;
	     break;

	   case _SLANG_BC_CALL_DIRECT:
	     (*addr->b.call_function) ();
	     break;

	   case _SLANG_BC_CALL_DIRECT_FRAME:
	     do_bc_call_direct_frame (addr->b.call_function);
	     break;

	   case _SLANG_BC_UNARY:
	     do_unary (addr->b.i_blk, _SLANG_BC_UNARY);
	     break;
	     
	   case _SLANG_BC_UNARY_FUNC:
	     /* Make sure we treat these like function calls since the
	      * parser took abs(x) to be a function call.
	      */
	     if (0 == _SL_increment_frame_pointer ())
	       {
		  do_unary (addr->b.i_blk, _SLANG_BC_UNARY);
		  (void) _SL_decrement_frame_pointer ();
	       }
	     break;
	     
	   case _SLANG_BC_DEREF_ASSIGN:
	     set_deref_lvalue (addr);
	     break;
	   case _SLANG_BC_SET_LOCAL_LVALUE:
	     set_lvalue_obj (addr->bc_sub_type, Local_Variable_Frame - addr->b.i_blk);
	     break;
	   case _SLANG_BC_SET_GLOBAL_LVALUE:
	     if (-1 == set_lvalue_obj (addr->bc_sub_type, &addr->b.nt_gvar_blk->obj))
	       do_name_type_error (addr->b.nt_blk);
	     break;
	   case _SLANG_BC_SET_INTRIN_LVALUE:
	     set_intrin_lvalue (addr);
	     break;
	   case _SLANG_BC_SET_STRUCT_LVALUE:
	     set_struct_lvalue (addr);
	     break;

	   case _SLANG_BC_FIELD:
	     (void) push_struct_field (addr->b.s_blk);
	     break;

	   case _SLANG_BC_SET_ARRAY_LVALUE:
	     set_array_lvalue (addr->bc_sub_type);
	     break;

#if _SLANG_HAS_DEBUG_CODE
	   case _SLANG_BC_LINE_NUM:
	     break;
#endif
	     
	   case _SLANG_BC_TMP:
	     tmp_variable_function (addr);
	     break;

#if _SLANG_OPTIMIZE_FOR_SPEED
	   case _SLANG_BC_LVARIABLE_AGET:
	     if (0 == push_local_variable (addr->b.i_blk))
	       do_bc_call_direct_frame (_SLarray_aget);
	     break;

	   case _SLANG_BC_LVARIABLE_APUT:
	     if (0 == push_local_variable (addr->b.i_blk))
	       do_bc_call_direct_frame (_SLarray_aput);
	     break;
	   case _SLANG_BC_INTEGER_PLUS:
	     if (0 == SLclass_push_int_obj (addr->bc_sub_type, (int) addr->b.l_blk))
	       do_binary (SLANG_PLUS);
	     break;

	   case _SLANG_BC_INTEGER_MINUS:
	     if (0 == SLclass_push_int_obj (addr->bc_sub_type, (int) addr->b.l_blk))
	       do_binary (SLANG_MINUS);
	     break;
#endif
#if 0
	   case _SLANG_BC_ARG_LVARIABLE:
	     (void) SLang_start_arg_list ();
	     push_local_variable (addr->b.i_blk);
	     break;
#endif
	   case _SLANG_BC_EARG_LVARIABLE:
	     push_local_variable (addr->b.i_blk);
	     (void) SLang_end_arg_list ();
	     break;

#if USE_COMBINED_BYTECODES
	   case _SLANG_BC_CALL_DIRECT_INTRINSIC:
	     (*addr->b.call_function) ();
	     addr++;
	     execute_intrinsic_fun (addr->b.nt_ifun_blk);
	     if (SLang_Error)
	       do_traceback(addr->b.nt_ifun_blk->name, 0, NULL);
	     break;

	   case _SLANG_BC_INTRINSIC_CALL_DIRECT:
	     execute_intrinsic_fun (addr->b.nt_ifun_blk);
	     if (SLang_Error)
	       {
		  do_traceback(addr->b.nt_ifun_blk->name, 0, NULL);
		  break;
	       }
	     addr++;
	     (*addr->b.call_function) ();
	     break;

	   case _SLANG_BC_CALL_DIRECT_LSTR:
	     (*addr->b.call_function) ();
	     addr++;
	     _SLang_dup_and_push_slstring (addr->b.s_blk);
	     break;

	   case _SLANG_BC_CALL_DIRECT_SLFUN:
	     (*addr->b.call_function) ();
	     addr++;
	     execute_slang_fun (addr->b.nt_fun_blk);
	     if (Lang_Break_Condition) goto handle_break_condition;
	     break;

	   case _SLANG_BC_CALL_DIRECT_INTRSTOP:
	     (*addr->b.call_function) ();
	     addr++;
	     /* drop */
	   case _SLANG_BC_INTRINSIC_STOP:
	     execute_intrinsic_fun (addr->b.nt_ifun_blk);
	     if (SLang_Error == 0)
	       return 1;
	     do_traceback(addr->b.nt_ifun_blk->name, 0, NULL);
	     break;

	   case _SLANG_BC_CALL_DIRECT_EARG_LVAR:
	     (*addr->b.call_function) ();
	     addr++;
	     push_local_variable (addr->b.i_blk);
	     (void) SLang_end_arg_list ();
	     break;

	   case _SLANG_BC_CALL_DIRECT_LINT:
	     (*addr->b.call_function) ();
	     addr++;
	     SLclass_push_int_obj (addr->bc_sub_type, (int) addr->b.l_blk);
	     break;

	   case _SLANG_BC_CALL_DIRECT_LVAR:
	     (*addr->b.call_function) ();
	     addr++;
	     push_local_variable (addr->b.i_blk);
	     break;
#endif				       /* USE_COMBINED_BYTECODES */

	   default:
	     SLang_verror (SL_INTERNAL_ERROR, "Byte-Code 0x%X is not valid", addr->bc_main_type);
	  }

	/* Someday I plan to add a 'signal' intrinsic function.  Then when a
	 * signal is caught, a variable will be set to one and that value of
	 * that variable will need to be monitored here, e.g.,
	 * if (Handle_Signal) handle_signal ();
	 * It would be nice to check only one variable instead of Handle_Signal
	 * and SLang_Error.  Perhaps I should phase out SLang_Error = xxx
	 * and used something like: SLang_set_error (code);  Then, I could
	 * use:
	 * if (Handle_Condition)
	 *   {
	 *      Handle_Condition = 0;
	 *      if (SLang_Error) ....
	 *      else if (Handle_Signal) handle_signal ();
	 *      else....
	 *   }
	 */
	if (SLang_Error)
	  {
	     if (-1 == do_inner_interp_error (err_block, addr_start, addr))
	       return 1;
	     if (SLang_Error)
	       return 1;

	     /* Otherwise, error cleared.  Continue onto next bytecode.
	      * Someday I need to add something to indicate where the
	      * next statement begins since continuing on the next
	      * bytecode is not really what is desired.
	      */
	     if (Lang_Break_Condition) goto handle_break_condition;
	  }
	addr++;
     }

   handle_break_condition:
   /* Get here if Lang_Break_Condition != 0, which implies that either
    * Lang_Return, Lang_Break, or Lang_Continue is non zero
    */
   if (Lang_Return)
     Lang_Break = 1;

   return 1;
}

/*}}}*/

/* The functions below this point are used to implement the parsed token
 * to byte-compiled code.
 */
/* static SLang_Name_Type **Static_Hash_Table; */

static SLang_Name_Type **Locals_Hash_Table;
static int Local_Variable_Number;
static unsigned int Function_Args_Number;
int _SLang_Auto_Declare_Globals = 0;
int (*SLang_Auto_Declare_Var_Hook) (char *);

static SLang_NameSpace_Type *This_Static_NameSpace;
static SLang_NameSpace_Type *Global_NameSpace;

#if _SLANG_HAS_DEBUG_CODE
static char *This_Compile_Filename;
#endif
static SLBlock_Type SLShort_Blocks[6];
/* These are initialized in add_table below.  I cannot init a Union!! */

static int Lang_Defining_Function;
static void (*Default_Variable_Mode) (_SLang_Token_Type *);
static void (*Default_Define_Function) (char *, unsigned long);

static int push_compile_context (char *);
static int pop_compile_context (void);

typedef struct
{
   int block_type;
   SLBlock_Type *block;		       /* beginning of block definition */
   SLBlock_Type *block_ptr;	       /* current location */
   SLBlock_Type *block_max;	       /* end of definition */
   SLang_NameSpace_Type *static_namespace;
}
Block_Context_Type;

static Block_Context_Type Block_Context_Stack [SLANG_MAX_BLOCK_STACK_LEN];
static unsigned int Block_Context_Stack_Len;

static SLBlock_Type *Compile_ByteCode_Ptr;
static SLBlock_Type *This_Compile_Block;
static SLBlock_Type *This_Compile_Block_Max;
static int This_Compile_Block_Type;
#define COMPILE_BLOCK_TYPE_FUNCTION	1
#define COMPILE_BLOCK_TYPE_BLOCK	2
#define COMPILE_BLOCK_TYPE_TOP_LEVEL	3

/* If it returns 0, DO NOT FREE p */
static int lang_free_branch (SLBlock_Type *p)
{
   /* Note: we look at 0,2,4, since these blocks are 0 terminated */
   if ((p == SLShort_Blocks)
       || (p == SLShort_Blocks + 2)
       || (p == SLShort_Blocks + 4)
       )
     return 0;

   while (1)
     {
	SLang_Class_Type *cl;

        switch (p->bc_main_type)
	  {
	   case _SLANG_BC_BLOCK:
	     if (lang_free_branch(p->b.blk))
	       SLfree((char *)p->b.blk);
	     break;

	   case _SLANG_BC_LITERAL:
	   case _SLANG_BC_LITERAL_STR:
	     /* No user types should be here. */
	     cl = _SLclass_get_class (p->bc_sub_type);
	     (*cl->cl_byte_code_destroy) (p->bc_sub_type, (VOID_STAR) &p->b.ptr_blk);
	     break;

	   case _SLANG_BC_FIELD:
	   case _SLANG_BC_SET_STRUCT_LVALUE:
	     SLang_free_slstring (p->b.s_blk);
	     break;

	   default:
	     break;

	   case 0:
	     return 1;
	  }
	p++;
     }
}

static void free_function_header (_SLBlock_Header_Type *h)
{
   if (h->num_refs > 1)
     {
	h->num_refs--;
	return;
     }

   if (h->body != NULL)
     {
	if (lang_free_branch (h->body))
	  SLfree ((char *) h->body);
     }

   SLfree ((char *) h);
}

static int push_block_context (int type)
{
   Block_Context_Type *c;
   unsigned int num;
   SLBlock_Type *b;

   if (Block_Context_Stack_Len == SLANG_MAX_BLOCK_STACK_LEN)
     {
	SLang_verror (SL_STACK_OVERFLOW, "Block stack overflow");
	return -1;
     }

   num = 5;    /* 40 bytes */
   if (NULL == (b = (SLBlock_Type *) SLcalloc (num, sizeof (SLBlock_Type))))
     return -1;

   c = Block_Context_Stack + Block_Context_Stack_Len;
   c->block = This_Compile_Block;
   c->block_ptr = Compile_ByteCode_Ptr;
   c->block_max = This_Compile_Block_Max;
   c->block_type = This_Compile_Block_Type;
   c->static_namespace = This_Static_NameSpace;

   Compile_ByteCode_Ptr = This_Compile_Block = b;
   This_Compile_Block_Max = b + num;
   This_Compile_Block_Type = type;

   Block_Context_Stack_Len += 1;
   return 0;
}

static int pop_block_context (void)
{
   Block_Context_Type *c;

   if (Block_Context_Stack_Len == 0)
     return -1;

   Block_Context_Stack_Len -= 1;
   c = Block_Context_Stack + Block_Context_Stack_Len;

   This_Compile_Block = c->block;
   This_Compile_Block_Max = c->block_max;
   This_Compile_Block_Type = c->block_type;
   Compile_ByteCode_Ptr = c->block_ptr;
   This_Static_NameSpace = c->static_namespace;

   return 0;
}

int _SLcompile_push_context (SLang_Load_Type *load_object)
{
   if (-1 == push_compile_context (load_object->name))
     return -1;

   if (NULL == (This_Static_NameSpace = _SLns_allocate_namespace (load_object->name, SLSTATIC_HASH_TABLE_SIZE)))
     {
	pop_compile_context ();
	return -1;
     }

   if (-1 == push_block_context (COMPILE_BLOCK_TYPE_TOP_LEVEL))
     {
	pop_compile_context ();
	return -1;
     }

   return 0;
}

int _SLcompile_pop_context (void)
{
   if (This_Compile_Block_Type == COMPILE_BLOCK_TYPE_TOP_LEVEL)
     {
	Compile_ByteCode_Ptr->bc_main_type = 0;
	if (lang_free_branch (This_Compile_Block))
	  SLfree ((char *) This_Compile_Block);
     }

   (void) pop_block_context ();
   (void) pop_compile_context ();

   if (This_Compile_Block == NULL)
     return 0;

#if 0
   if (This_Compile_Block_Type != COMPILE_BLOCK_TYPE_TOP_LEVEL)
     {
	SLang_verror (SL_INTERNAL_ERROR, "Not at top-level");
	return -1;
     }
#endif

   return 0;
}

/*{{{ Hash and Name Table Functions */

static SLang_Name_Type *locate_name_in_table (char *name, unsigned long hash,
					      SLang_Name_Type **table, unsigned int table_size)
{
   SLang_Name_Type *t;
   char ch;

   t = table [(unsigned int) (hash % table_size)];
   ch = *name++;

   while (t != NULL)
     {
	if ((ch == t->name[0])
	    && (0 == strcmp (t->name + 1, name)))
	  break;

	t = t->next;
     }

   return t;
}

static SLang_Name_Type *locate_namespace_encoded_name (char *name, int err_on_bad_ns)
{
   char *ns, *ns1;
   SLang_NameSpace_Type *table;
   SLang_Name_Type *nt;

   ns = name;
   name = strchr (name, '-');
   if ((name == NULL) || (name [1] != '>'))
     name = ns;

   ns1 = SLang_create_nslstring (ns, (unsigned int) (name - ns));
   if (ns1 == NULL)
     return NULL;
   if (ns != name)
     name += 2;
   ns = ns1;

   if (*ns == 0)
     {
	/* Use Global Namespace */
	SLang_free_slstring (ns);
	return locate_name_in_table (name, _SLcompute_string_hash (name),
				     Global_NameSpace->table, Global_NameSpace->table_size);
     }

   if (NULL == (table = _SLns_find_namespace (ns)))
     {
	if (err_on_bad_ns)
	  SLang_verror (SL_SYNTAX_ERROR, "Unable to find namespace called %s", ns);
	SLang_free_slstring (ns);
	return NULL;
     }
   SLang_free_slstring (ns);

   /* FIXME: the hash table size should be stored in the hash table itself */
   nt = locate_name_in_table (name, _SLcompute_string_hash (name),
			      table->table, table->table_size);
   if (nt == NULL)
     return NULL;

   switch (nt->name_type)
     {
	/* These are private and cannot be accessed through the namespace. */
      case SLANG_PVARIABLE:
      case SLANG_PFUNCTION:
	return NULL;
     }
   return nt;
}

static SLang_Name_Type *locate_hashed_name (char *name, unsigned long hash)
{
   SLang_Name_Type *t;

   if (Lang_Defining_Function)
     {
	t = locate_name_in_table (name, hash, Locals_Hash_Table, SLLOCALS_HASH_TABLE_SIZE);
	if (t != NULL)
	  return t;
     }

   if ((This_Static_NameSpace != NULL)
       && (NULL != (t = locate_name_in_table (name, hash, This_Static_NameSpace->table, This_Static_NameSpace->table_size))))
     return t;

   t = locate_name_in_table (name, hash, Global_NameSpace->table, Global_NameSpace->table_size);
   if (NULL != t)
     return t;

   return locate_namespace_encoded_name (name, 1);
}

SLang_Name_Type *_SLlocate_name (char *name)
{
   return locate_hashed_name (name, _SLcompute_string_hash (name));
}

static SLang_Name_Type *
add_name_to_hash_table (char *name, unsigned long hash,
			unsigned int sizeof_obj, unsigned char name_type,
			SLang_Name_Type **table, unsigned int table_size,
			int check_existing)
{
   SLang_Name_Type *t;

   if (check_existing)
     {
	t = locate_name_in_table (name, hash, table, table_size);
	if (t != NULL)
	  return t;
     }

   if (-1 == _SLcheck_identifier_syntax (name))
     return NULL;

   t = (SLang_Name_Type *) SLmalloc (sizeof_obj);
   if (t == NULL)
     return t;

   memset ((char *) t, 0, sizeof_obj);
   if (NULL == (t->name = _SLstring_dup_hashed_string (name, hash)))
     {
	SLfree ((char *) t);
	return NULL;
     }
   t->name_type = name_type;

   hash = hash % table_size;
   t->next = table [(unsigned int)hash];
   table [(unsigned int) hash] = t;

   return t;
}

static SLang_Name_Type *
add_global_name (char *name, unsigned long hash,
		 unsigned char name_type, unsigned int sizeof_obj,
		 SLang_NameSpace_Type *ns)
{
   SLang_Name_Type *nt;
   SLang_Name_Type **table;
   unsigned int table_size;
   
   table = ns->table;
   table_size = ns->table_size;

   nt = locate_name_in_table (name, hash, table, table_size);
   if (nt != NULL)
     {
	if (nt->name_type == name_type)
	  return nt;

	SLang_verror (SL_DUPLICATE_DEFINITION, "%s cannot be re-defined", name);
	return NULL;
     }

   return add_name_to_hash_table (name, hash, sizeof_obj, name_type,
				  table, table_size, 0);
}

static int add_intrinsic_function (SLang_NameSpace_Type *ns,
				   char *name, FVOID_STAR addr, unsigned char ret_type,
				   unsigned int nargs, va_list ap)
{
   SLang_Intrin_Fun_Type *f;
   unsigned int i;

   if (-1 == init_interpreter ())
     return -1;
   
   if (ns == NULL) ns = Global_NameSpace;

   if (nargs > SLANG_MAX_INTRIN_ARGS)
     {
	SLang_verror (SL_APPLICATION_ERROR, "Function %s requires too many arguments", name);
	return -1;
     }

   if (ret_type == SLANG_FLOAT_TYPE)
     {
	SLang_verror (SL_NOT_IMPLEMENTED, "Function %s is not permitted to return float", name);
	return -1;
     }

   f = (SLang_Intrin_Fun_Type *) add_global_name (name, _SLcompute_string_hash (name),
						  SLANG_INTRINSIC, sizeof (SLang_Intrin_Fun_Type),
						  ns);

   if (f == NULL)
     return -1;

   f->i_fun = addr;
   f->num_args = nargs;
   f->return_type = ret_type;

   for (i = 0; i < nargs; i++)
     f->arg_types [i] = va_arg (ap, unsigned int);

   return 0;
}

int SLadd_intrinsic_function (char *name, FVOID_STAR addr, unsigned char ret_type,
			      unsigned int nargs, ...)
{
   va_list ap;
   int status;

   va_start (ap, nargs);
   status = add_intrinsic_function (NULL, name, addr, ret_type, nargs, ap);
   va_end (ap);

   return status;
}

int SLns_add_intrinsic_function (SLang_NameSpace_Type *ns, 
				 char *name, FVOID_STAR addr, unsigned char ret_type,
				 unsigned int nargs, ...)
{
   va_list ap;
   int status;

   va_start (ap, nargs);
   status = add_intrinsic_function (ns, name, addr, ret_type, nargs, ap);
   va_end (ap);

   return status;
}

int SLns_add_intrinsic_variable (SLang_NameSpace_Type *ns,
				   char *name, VOID_STAR addr, unsigned char data_type, int ro)
{
   SLang_Intrin_Var_Type *v;

   if (-1 == init_interpreter ())
     return -1;
   
   if (ns == NULL) ns = Global_NameSpace;

   v = (SLang_Intrin_Var_Type *)add_global_name (name,
						 _SLcompute_string_hash (name),
						 (ro ? SLANG_RVARIABLE : SLANG_IVARIABLE),
						 sizeof (SLang_Intrin_Var_Type),
						 ns);
   if (v == NULL)
     return -1;

   v->addr = addr;
   v->type = data_type;
   return 0;
}
  
int SLadd_intrinsic_variable (char *name, VOID_STAR addr, unsigned char data_type, int ro)
{
   return SLns_add_intrinsic_variable (NULL, name, addr, data_type, ro);
}

static int
add_slang_function (char *name, unsigned char type, unsigned long hash,
		    unsigned int num_args, unsigned int num_locals,
#if _SLANG_HAS_DEBUG_CODE
		    char *file,
#endif
		    _SLBlock_Header_Type *h, 
		    SLang_NameSpace_Type *ns)
{
   _SLang_Function_Type *f;
   
#if _SLANG_HAS_DEBUG_CODE
   if ((file != NULL)
       && (NULL == (file = SLang_create_slstring (file))))
     return -1;
#endif

   f = (_SLang_Function_Type *)add_global_name (name, hash,
						type,
						sizeof (_SLang_Function_Type),
						ns);
   if (f == NULL)
     {
#if _SLANG_HAS_DEBUG_CODE
	SLang_free_slstring (file);    /* NULL ok */
#endif
	return -1;
     }

   if (f->v.header != NULL)
     {
	if (f->nlocals == AUTOLOAD_NUM_LOCALS)
	  SLang_free_slstring ((char *)f->v.autoload_filename); /* autoloaded filename */
	else
	  free_function_header (f->v.header);
     }

#if _SLANG_HAS_DEBUG_CODE
   if (f->file != NULL) SLang_free_slstring (f->file);
   f->file = file;
#endif
   f->v.header = h;
   f->nlocals = num_locals;
   f->nargs = num_args;

   return 0;
}

int SLang_autoload (char *name, char *file)
{
   _SLang_Function_Type *f;
   unsigned long hash;

   hash = _SLcompute_string_hash (name);
   f = (_SLang_Function_Type *)locate_name_in_table (name, hash, Global_NameSpace->table, Global_NameSpace->table_size);

   if ((f != NULL)
       && (f->name_type == SLANG_FUNCTION)
       && (f->v.header != NULL)
       && (f->nlocals != AUTOLOAD_NUM_LOCALS))
     {
	/* already loaded */
	return 0;
     }

   file = SLang_create_slstring (file);
   if (-1 == add_slang_function (name, SLANG_FUNCTION, hash, 0, AUTOLOAD_NUM_LOCALS,
#if _SLANG_HAS_DEBUG_CODE
				 file,
#endif
				 (_SLBlock_Header_Type *) file,
				 Global_NameSpace))
     {
	SLang_free_slstring (file);
	return -1;
     }

   return 0;
}

SLang_Name_Type *_SLlocate_global_name (char *name)
{
   unsigned long hash;

   hash = _SLcompute_string_hash (name);
   return locate_name_in_table (name, hash, Global_NameSpace->table, 
				Global_NameSpace->table_size);
}

/*}}}*/

static void free_local_variable_table (void)
{
   unsigned int i;
   SLang_Name_Type *t, *t1;

   for (i = 0; i < SLLOCALS_HASH_TABLE_SIZE; i++)
     {
	t = Locals_Hash_Table [i];
	while (t != NULL)
	  {
	     SLang_free_slstring (t->name);
	     t1 = t->next;
	     SLfree ((char *) t);
	     t = t1;
	  }
	Locals_Hash_Table [i] = NULL;
     }
   Local_Variable_Number = 0;
}

/* call inner interpreter or return for more */
static void lang_try_now(void)
{
   Compile_ByteCode_Ptr++;
   if (This_Compile_Block_Type != COMPILE_BLOCK_TYPE_TOP_LEVEL)
     return;

   Compile_ByteCode_Ptr->bc_main_type = 0;  /* so next command stops after this */

   /* now do it */
   inner_interp (This_Compile_Block);
   (void) lang_free_branch (This_Compile_Block);
   Compile_ByteCode_Ptr = This_Compile_Block;
}

SLang_Name_Type *SLang_get_fun_from_ref (SLang_Ref_Type *ref)
{
   if (ref->is_global)
     {
	SLang_Name_Type *nt = ref->v.nt;

	switch (nt->name_type)
	  {
	   case SLANG_PFUNCTION:
	   case SLANG_FUNCTION:
	   case SLANG_INTRINSIC:
	   case SLANG_MATH_UNARY:
	   case SLANG_APP_UNARY:
	     return nt;
	  }
	SLang_verror (SL_TYPE_MISMATCH,
		      "Reference to a function expected.  Found &%s", 
		      nt->name);
     }

   SLang_verror (SL_TYPE_MISMATCH,
		 "Reference to a function expected");
   return NULL;
}

int SLexecute_function (SLang_Name_Type *nt)
{
   unsigned char type;
   char *name;

   if (SLang_Error)
     return -1;

   type = nt->name_type;
   name = nt->name;

   switch (type)
     {
      case SLANG_PFUNCTION:
      case SLANG_FUNCTION:
	execute_slang_fun ((_SLang_Function_Type *) nt);
	break;

      case SLANG_INTRINSIC:
	execute_intrinsic_fun ((SLang_Intrin_Fun_Type *) nt);
	break;

      case SLANG_MATH_UNARY:
      case SLANG_APP_UNARY:
	inner_interp_nametype (nt);
	break;

      default:
	SLang_verror (SL_TYPE_MISMATCH, "%s is not a function", name);
	return -1;
     }

   if (SLang_Error)
     {
	SLang_verror (SLang_Error, "Error while executing %s", name);
	return -1;
     }

   return 1;
}

int SLang_execute_function (char *name)
{
   SLang_Name_Type *entry;

   if (NULL == (entry = SLang_get_function (name)))
     return 0;

   return SLexecute_function (entry);
}

/* return S-Lang function or NULL */
SLang_Name_Type *SLang_get_function (char *name)
{
   SLang_Name_Type *entry;

   if (NULL == (entry = locate_namespace_encoded_name (name, 0)))
     return NULL;

   if ((entry->name_type == SLANG_FUNCTION)
       || (entry->name_type == SLANG_INTRINSIC))
     return entry;

   return NULL;
}

static void lang_begin_function (void)
{
   if (This_Compile_Block_Type != COMPILE_BLOCK_TYPE_TOP_LEVEL)
     {
	SLang_verror (SL_SYNTAX_ERROR, "Function nesting is illegal");
	return;
     }
   Lang_Defining_Function = 1;
   (void) push_block_context (COMPILE_BLOCK_TYPE_FUNCTION);
}

#if USE_COMBINED_BYTECODES
static void optimize_block (SLBlock_Type *b)
{
   while (1)
     {
	switch (b->bc_main_type)
	  {
	   case 0:
	     return;
	     
	   default:
	     b++;
	     break;

	   case _SLANG_BC_CALL_DIRECT:
	     b++;
	     switch (b->bc_main_type)
	       {
		case 0:
		  return;
		case _SLANG_BC_INTRINSIC:
		  if ((b+1)->bc_main_type == 0)
		    {